注册 登录
编程论坛 C++教室

还是继承与派生。。。

sunflower44 发布于 2011-08-22 00:13, 744 次点击
先上代码~~~

 #include<iostream.h>
        class A{
        private:
          int a;
        public:
          A(){ a=0;cout<<"A′s defanlt constructor called.\n"; }
          A(int i){ a=i;cout<<"A′s constructor called.\n"; }
          void print(){ cout<<a<<","; }
          ~A(){ cout<<"A′s destructor called.\n"; }
          int Geta(){ return a; }
        };
        class B: public A{
        public:
          B(){ b=0;cout<<"B′s defanlt constructor called.\n"; }
          B(int i,int j,int k):A(i),aa(j){ b=k;  cout<<"B′s constructor called.\n"; }
          void print();
          ~B(){ cout<<"B′s destructor called.\n"; }
        private:
          int b;
          A aa;                //子对象,或称为成员对象
        };
       void B::print(){
          A::print();
          cout<<b<<","<<aa.Geta()<<endl;
        }
        void main(){
          B bb[2]={B(1,2,5),B(3,4,7)};
          for(int i=0;i<2;i++) bb[i].print();
        }


运行结果:
A's constructor called.
A's constructor called.
B's constructor called.
A's constructor called.
A's constructor called.
B's constructor called.
1,5,2
3,7,4
B's destructor called.
A's destructor called.
A's destructor called.
B's destructor called.
A's destructor called.
A's destructor called.


我想问下,为什么在子对象调用构造函数的时候,调用的是
 A(int i){ a=i;cout<<"A′s constructor called.\n"; }
而不是
 A(){ a=0;cout<<"A′s defanlt constructor called.\n"; }
子对象aa不是不带参数吗?
后面析构函数调用同问。。。。不懂啊,到底什么时候调用缺省构造函数和缺省析构函数?
11 回复
#2
rjsp2011-08-22 08:19
那你写 aa(j) 是干什么的呀
#3
天蝎殿2011-08-22 11:01
子对象aa是带参数的。
以main function的B(1, 2, 5)为例子:
B(1, 2, 5) =  
                B(1,2,5)
                : A(1)
                , aa(2)
                {
                  b=5;  
                  cout<<"B′s constructor called.\n";
                 }

于是,当B(1,2,5)被叫到时, contructor开始调出 private member variable A aa 的constructor A(int i)
导致第一个正式被打印出结果是A(int i){}里面的内容。


并且虽然不知道楼主想要问什么,不过继承和派生都没有用到。。。
先学一下virtual和protected member variable吧。
#4
xg56992011-08-22 11:20
和上次的问题一模一样,都白和你讲了.
#5
jcw081201102011-08-22 15:11
我上次说了那么多你都没看! 痛心啊~~~~~~~~
你的 B bb 调用的是有参数的构造函数;所以a的构造也是调用的有参构造!!你试试 B b ; 看看结果就知道区别所在了!
#6
sunflower442011-08-22 21:17
回复 5楼 jcw08120110
试代码没什么啊,可是我不知道为什么会出现那样的结果。。。
其实我想问的就是,调用含参的构造或析构函数还是调用默认的构造或析构函数,到底看哪里啊?判断子对象是否含参数,到底看哪里的代码啊?
#7
sunflower442011-08-22 21:20
回复 2楼 rjsp
你的意思是说,判断子对象带不带参数,要看
B(int i,int j,int k):A(i),aa(j){ b=k;  cout<<"B′s constructor called.\n"; }
这一行代码?
也就是要看派生类构造函数初始化表中的子对象有没有参数?
#8
specilize2011-08-22 21:58
请问楼主,你说的是不是这个意思
在class B 中写private A aa 就犹如在main函数中写
int main()
{
     A aa;
     return 0;
}
也就是说相当于是再class B中定义了一个变量
因为在main函数中有一个 A(){ a=0;cout<<"A′s defanlt constructor called.\n"; }的调用,所以B的构造函数B(int i,int j,int k):A(i),aa(j){ b=k;  cout<<"B′s constructor called.\n"; }
也应该有一个A′s defanlt constructor called.\n这样的东西出现
#9
sunflower442011-08-22 22:29
回复 8楼 specilize
不是。。。没那么复杂。我就是看着
A aa;                //子对象,或称为成员对象
这行代码对aa没有初始化值,所以要调用那个没有参数的构造函数。。。
如果写的是
A aa(1);                //子对象,或称为成员对象
我就用那个有参数的了。
因为我不知道从什么代码判断有参还是无参
#10
specilize2011-08-23 07:40
那不就是我说的那个意思了,你把
class B: public A{
        private:
          int b;
          A aa;                //子对象,或称为成员对象
        };
中的A aa理解成相当于是在定义一个变量,所以就应该调用那个没有参数的A的构造函数
不然你这样试试
class B: public A{
        private:
          int b;
          A aa(1);                //子对象,或称为成员对象
        };
它肯定会给你提示错误的,所以就说明不是你理解的那个意思了嘛
它这样写
class B: public A{
        private:
          int b;
          A aa;                //子对象,或称为成员对象
        };
的意思不是在定义一个A变量,而是说B中含有A这个成员,而B中的A的初始化是在
B(int i,int j,int k):A(i),aa(j){ b=k;  cout<<"B′s constructor called.\n"; }这里面的aa(j)进行初始化,还是不懂你就这样写B(int i,int j,int k):A(i),aa(){ b=k;  cout<<"B′s constructor called.\n"; }或者这样写
B(int i,int j,int k):A(i){ b=k;  cout<<"B′s constructor called.\n"; }就能看到
A′s defanlt constructor called了
#11
xg56992011-08-23 12:16
回复 9楼 sunflower44
首先你要搞清楚调构造函数是被调用
什么是被?就是你被我亲一下,是我亲的你而不是
你自己亲自己。
   好了,回到程序中来我们得知任何构造函数都是被调用的
那是什么调用构造函数的呢?就是对象。
   当创建一个对象时对象一定会调用一个构造函数
为自己初始化。你说A aa;不知道调用哪个构造函数
别说你不知道,在写完类的时候编译器它自己也不知道
因为构造函数是被调用!没有创建对象之前只不可能知道的!
    当创建了对象时,编译器才知道。那么只要找到是谁(对象)调用了它就可以知道
调用哪个构造函数了
   就好比说你被亲了一下不知道亲在哪个地方,是嘴巴上还是
胸口上,那么你只要找到那个亲你的人,就知道了
   我们就来找是谁掉用了子对象
   在main主函数中创建了对象,那么调用子对象的构造函数,
在调用子对象构造函数过程中会先掉用父类的构造函数,
然后调用子对象的构造函数,在你的子类中又有一个父类的对象
那么子对象的构造函数先等等,从大到小,无论是吃饭洗澡都是长辈先吃
接着在儿子吃。所以当儿子类要创建对象时先会把父类的对象都创造完了
在创建儿子。
    所以会先创建A aa;这个对象,这个对象默认是不带参数的,但是子类调用的
构造函数里初始化了这个对象使他带有参数
    毕竟是儿子叫爸爸吃饭的,儿子可以让爸爸直接吃饭,也可以让爸爸叫妈妈
一起来吃饭!儿子类的构造函数中的:aa(妈妈)起到了这个作用,不仅可以叫妈妈,
,你还可以叫:aa(妈妈,爷爷,奶奶,小三),只要爸爸认识这些人(父类中的数据成员)。
     由于爸爸很懒,你不叫他这么做他只会自己一个人吃饭谁也不叫。

[ 本帖最后由 xg5699 于 2011-8-23 12:30 编辑 ]
#12
jcw081201102011-08-23 15:08
回复 11楼 xg5699
学习~ 学习;
创建对象肯定会调用构造函数的;这个大家都知道;  创建子类的对象肯定会调用子类的构造函数,不过在这之前会先调用基类的构造函数;   那么究竟该调用什么构造函数呢? 这个要看你创建的对象; 如果你创建的对象没有参数,那么就调用没有参数的构造函数;例如 B b;你看这个对象b是没有参数的 所以调用无参构造函数;如果是 B b(1,2,5)那么就是调用含3个参数的构造函数;
1