Chinaunix首页 | 论坛 | 博客
  • 博客访问: 326622
  • 博文数量: 26
  • 博客积分: 1128
  • 博客等级: 少尉
  • 技术积分: 313
  • 用 户 组: 普通用户
  • 注册时间: 2010-07-04 13:39
文章分类

全部博文(26)

文章存档

2012年(2)

2011年(10)

2010年(14)

分类: C/C++

2010-10-30 12:58:50

最近C++刚自学到运算符重载,在做一个String类的实验时,出现了很多让我觉得很诡异的问题,两个学长也帮我解决这些问题,发现问题是出在构造函数这里。纠结了两天的所谓诡异的问题,终于在今天被解决咯。。程序里出现的所有问题也被我搞清楚了。通过这次的问题程序,我对构造函数,尤其是默认构造函数有了更深一步的认识和了解,以下结合我的问题程序小小总结一下,平时不很受关注的默认构造函数。


默认构造函数(default constructor)---无参数

1.定义:在未提供显式的初始化值时,被用来创建对象的构造函数;

注:系统默认的构造函数只创建对象,并不做任何初始化工作。

e.g: String ob2;

若没有提供任何构造函数,则C++将自动提供默认构造函数,即系统默认构造函数。形式类似于这样:

String:: String ( ) { } ---> 不做任何工作;

注:

当且仅当没有定义任何构造函数时,编译器才会提供默认构造函数。所以如果已经为类定义了构造函数,您就必须为它提供默认构造函数。若提供了非默认构造函数(即普通构造函数),但没有提供默认构造函数。则当您声明: String ob2;时编译会出错。

String.cpp: In function ‘int main()’:

String.cpp:95: error: no matching function for call to ‘String::String()’

String.cpp:37: note: candidates are: String::String(const String&)

//这是我定义的复制构造函数

String.cpp:29: note: String::String(const char*)

//这是我的普通构造函数

提示没有找到默认构造函数匹配的格式,并给出了你自己定义的普通函数的格式,提示只有这两个候选构造函数,而没有默认构造函数,那么您就不能只main函数中像这样String ob2;只创建对象了。


2.定义默认构造函数的两种方式:

1)给已有的构造函数的所有参数提供默认值:

e.g:

Complex (float r=0, float i=0); //在类体中函数声明的格式

在类体外定义是还应是Complex ( float r, float i) { … }

注:

 当类对象成员有指针变量时请注意您构造函数中的判断,后面马上说到。

在我的String类中用过这样的定义方式

String (const char *str = NULL);

类是这样定义的:

class String

{

public:

// String ( ); //先把自定义的默认构造函数隐掉,因为两种方式不能同时出现

String ( const char *str=NULL ); //在此声明

String ( const String &other );

~String ( );

String & operator = ( char *str );

String & operator = ( const String &other );

int operator == ( String &other );

int operator == ( char *str );

void print ( );

private:

char *m_data; //类中有指针变量型的对象成员

int length;

};

String :: String ( const char *str ) //普通构造函数

{

length = strlen ( str );

m_data = new char [length + 1];

strcpy ( m_data, str );

}

然后我在进行编译时,是通过的,然而在运行时却出现了段错误。也就是说如果按以上这个方式定义时,类中的指针变量指向的是非法空间;所以请注意,当您的类中定义了指针变量,那么在您的普通构造函数里,就需要做一个判断if (str == NULL)然后给m_data开辟一个空间去存放'\0';

也就是说您的构造函数应该这样写:

String :: String ( const char *str )

{

if (str == NULL) //这个判断很重要哦,小心你的指针指向非法空间出现段错误··

{

m_data = new char[1];

*m_data = '\0';

}

else

{

length = strlen ( str );

m_data = new char [length + 1];

strcpy ( m_data, str );

}

}

如果您不想做此步的判断,那么就可以选择使用第二种方式定义默认构造函数。

2)通过函数重载来定义另一个构造函数-----一个没有参数的构造函数

e.g:

String (); //类体中声明;

String :: String ()

{

m_data = new char[1]; //空间任意开辟

length = 4;

}

注:

若在此处给指针变量开辟了空间,那么在以后其他代码实现部分,要对此指针所指向的地址内容进行修改操作时,要先delete释放原有空间,再重新开辟。若不释放,编译可以通过,运行也正常,但是会造成内存泄漏。

由于只能有一个默认构造函数,所以不能同时采用以上两种方式。编译时会出错。提示是在重载默认构造函数时有二义性:

String.cpp: In function ‘int main()’:

//main函数中隐式定义String ob2;

String.cpp:95: error: call of overloaded ‘String()’ is ambiguous

String.cpp:29: note: candidates are: String::String(const char*)

String.cpp:22: note: String::String()



TIPS

设计类时通常应该提供对所以类成员做隐式初始化的默认构造函数。


使用上述任何一种方式(无参或所以参数都有默认值)创建了默认构造函数后,就可以隐式初始化:

e.g: String ob2;

但是,不要被非默认构造函数的隐式形式所误导:

e.g: String ob1(“wuyun”); //接收参数的构造函数

String ob2 ( ); // 返回String对象的函数





参考文献: 《C++ Primmer Plus》第五版

阅读(1922) | 评论(3) | 转发(0) |
给主人留下些什么吧!~~

wykitty2011-07-23 19:56:49

chinaunix网友: 关于String类的学习你可以看孙悦的《高质量C++》,里面有专门的章节讲String的4个函数,面试中很有用...........

嗯嗯~~谢谢

chinaunix网友2011-06-07 15:18:46

关于String类的学习你可以看孙悦的《高质量C++》,里面有专门的章节讲String的4个函数,面试中很有用......

chinaunix网友2010-10-31 19:15:24

很好的, 收藏了 推荐一个博客,提供很多免费软件编程电子书下载: http://free-ebooks.appspot.com