关于在类中声明对象数据成员时的初始化问题,切判!

gongjin1983ccc 2007-09-16 12:35:48
近来有一个程序一直困扰着我,希望有高手不吝赐教:
代码如下:

#include<iostream>
using namespace std;

class a //定义一个类
{
private:
int b,c;
public:
a(int b1,int c1):b(b1),c(c1){}//带参数的构造函数--语句1
a(int b1=1,int c1=1):b(b1),c(c1){}//带默认参数的构造函数--语句2
a(const a& a1){b=a1.b,c=a1.c;}//拷贝构造函数--语句3

};

class b //定义第二个类
{
private:
int d;
// a a0(1,2);这样写编译器会提示出错--语句4
a a0;//但如果这样写又怎么初始化a0呢?继续往下看--语句5

public:
//b(int d1,a a1):d(d1),a0(a1){}//如果用参数化列表写b的构造函数,那么编译通过,但是如果写成下面的形式,并在类外定义构造函数,则编译不通过,会出提示: no matching function for call to `a::a()',为什么?
b(int d1,a a1);
b(int d1);//另一种构造,不管a0

};

b::b(int d1)
{
d=d1}
b::b(int d1,a a1)
{
a0=a1;
d=0;
}

int main(int argc,char* argv[])
{
a t(5,6);
b b1(2,t);

}
操作系统:Winxp sp2
编译环境:Dev-c++ 4.9.9.2

问题和现象描述:
1.在类中声明(或定义)另一个类的对象作为数据成员时算“定义”还是算“声明”?
2.为什么在b中声明类a的对象时不能调用a的构造函数?
3.因为构造函数不能被用户(只能被系统)显式调用,而在类b中声明时又不让调用a0的构造函数,那该怎么初始化呢?似乎有点矛盾
现象:如果a中只有语句2(带参数),b中只有语句5,那么编译通过
如果a中只有语句1(不带参数),b中只有语句5,那么编译不通过,提示
no matching function for call to `a::a()';之后,在a中加入语句3,仍有相同提示,错误行出在b的构造函数入口出(是b::b(int d1)下面一行)
4参数化列表和普通构造有什么不同?

真诚希望高手给个系统而完整的分析和总结,感激不尽!!
...全文
348 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
独孤过儿 2007-09-16
  • 打赏
  • 举报
回复
大致看了一下,应该能给你一个比较全面的答复。如下:

首先,你定义的两个构造函数,有一个是没有用的,

这个函数是多余的,它的行为完全包含在带有默认参数的构造函数中
a(int b1,int c1):b(b1),c(c1){}

1.在类中声明(或定义)另一个类的对象作为数据成员时算“定义”还是算“声明”?

如果你用 a a0的形式,那它就是定义,需要实际分配内存单元的。

2.为什么在b中声明类a的对象时不能调用a的构造函数?
谁说不可以调用了啊?看这个例子:
#include<iostream>
using namespace std;

class a{
public:
a()
{
cout<<"a constructor!"<<endl;
}
~a()
{
cout<<"a destructor!"<<endl;
}
};

class b{
private:
a a0;
public:
b()
{
cout<<"b constructor!"<<endl;
}
~b()
{
cout<<"b destructor!"<<endl;
}
};

int main()
{
b b0;
return 0;
}

3.因为构造函数不能被用户(只能被系统)显式调用,而在类b中声明时又不让调用a0的构造函数,那该怎么初始化呢?似乎有点矛盾
可以在构造B的时候用参数列表,将数据传递给A类。

现象:如果a中只有语句2(带参数),b中只有语句5,那么编译通过
那是因为有默认的参数,所以没有问题。

如果a中只有语句1(不带参数),b中只有语句5,那么编译不通过,提示
no matching function for call to `a::a()';之后,在a中加入语句3,仍有相同提示,错误行出在b的构造函数入口出(是b::b(int d1)下面一行)
这很正常啊,因为a类的构造函数列表是空的,而你现在给了它两个参数,它当然说类型不匹配了啊。

4.参数化列表和普通构造有什么不同?
这个比较复杂。举个例子,假如不能确定某个类的成员是在什么时间构建的,就只能用参数化列表而不能用构造函数;还有,有的时候构造函数没有权限直接访问某个数据成员的时候,也只能通过参数化列表来完成构造。
iambic 2007-09-16
  • 打赏
  • 举报
回复

class a //定义一个类
{
private:
int b,c;
public:

//这个构造函数和第二个构造函数重复了,删掉。
//a(int b1,int c1):b(b1),c(c1){}//带参数的构造函数--语句1

a(int b1=1,int c1=1):b(b1),c(c1){}//带默认参数的构造函数--语句2

//这个拷贝构造函数没用,删掉。
//a(const a& a1){b=a1.b,c=a1.c;}//拷贝构造函数--语句3

};
gongjin1983ccc 2007-09-16
  • 打赏
  • 举报
回复
fetag(过儿思念小龙女)
谢谢你啊,我看了看书,明白了不少。这东西别人点一下,自己再看一下,效果很好的。
敬礼!
独孤过儿 2007-09-16
  • 打赏
  • 举报
回复
因为你的类里面的数据成员都是数据,而没有指针以及动态申请的内存,这在复制的时候,默认

的构造函数的行为已经足够用了,不需要拷贝构造函数。

你翻一下书,看看什么时候需要拷贝构造函数就明白了。我明白道理,但是说不清楚,呵呵
gongjin1983ccc 2007-09-16
  • 打赏
  • 举报
回复
iambic你好,为什么我那个拷贝构造函数没用呢?
gongjin1983ccc 2007-09-16
  • 打赏
  • 举报
回复
多谢以上两位,我有点明白了许多。但还是有点不明白:其实原来的例子要更复杂一些, b中还有一个二维数组,这样的话b的构造函数就没办法用参数化列表的形式了,必须用函数体的形式,b(int d1,a a1);
在类外定义:
b::b(int d1,a a1)
{
a0=a1;
//对原来那个数组初始化
d=0;
}
这样一来编译器就通不过,提示没有匹配的a的构造函数
正如你上面所说,b可以调用a的构造函数,但要想通过b向a0传递参数,编译器似乎总是不通过,怎么才能传参数以初始话呢?

65,180

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧