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

请教大家一个简单的程序

boyyang4894 发布于 2007-03-31 19:11, 1499 次点击

谁能告诉我执行该程序的顺序,谢谢;

#include<iostream>
using namespace std;
class A
{public:
virtual void fun1()
{cout<<"a1";}
virtual void fun2()
{cout<<"a2";}
};
class B: public A
{public:
B():A()
{fun1();}
void fun()
{fun1();}
~B()
{fun2();}
};
class C: public B
{
public:
void fun1()
{cout<<"c1";}
void fun2()
{cout<<"c2";}
~C()
{fun2();}
};

int main()
{
C obj;
obj.fun();

return 0;
}

12 回复
#2
游乐园2007-03-31 19:31

从主函数开始执行

C obj: 创建C的对象,调用类C的构造函数,没有则继承父类的构造函数即B的构造函数,而B的构造函数是由其父类A初始化的

所以对象创建顺序为: A 创建 B创建 C创建 , 具体:

1.C创建后调用B的构造函数 fun1() 而B的构在函数是A初始的所以输出 a1
2.obj.fun() 调用父类B的fun() 调用fun1() 输出 c1
3.析构 C的对象 调用fun2() 输出c2
4.析构 B的对象 调用fun2() 即从父类A继承过来的fun2 输出a2
5.析构 A的对象 如果你在A类里写个析构函数 ~A() {cout<<"end";} 最后就会输出 end

[此贴子已经被作者于2007-3-31 19:32:30编辑过]

#3
boyyang48942007-03-31 19:40
回复:(游乐园)从主函数开始执行 C obj: 创建C的对象...
可不可以这样看:
1. C创建后调用类C的构造函数,由于C是B的派生则先调用B的构,又因为B是A的派生,所以先调用A的构造.A没有定义则系统建立一个空的构造函数并执行.然后在执行B的构造.在B构造中有fun1()//我想问此时执行的是哪个fun1(),为什么是类A中的?
最后是C中的构造,同类A一样由系统自动生成空函数并执行.
2.obj.fun() 调用类B中void fun().//
fun()中的fun1()又是哪个,这怎么又是C中的了?
3.析构 C的对象 调用fun2() 输出c2
4.析构 B的对象 调用fun2() 即从父类A继承过来的fun2 输出a2
//为什么调用的是A中的fun2()?


[此贴子已经被作者于2007-3-31 20:06:31编辑过]

#4
游乐园2007-03-31 20:00
不同的,一个是C调用fun1() 一个是B调用fun1()

因为C里重写了fun1()所有调用的是自己的

B里是继承A的fun1()
#5
dlcdavid2007-03-31 20:06
以下是引用游乐园在2007-3-31 19:31:47的发言:

所以对象创建顺序为: A 创建 B创建 C创建 , 具体:

1.C创建后调用B的构造函数 fun1() 而B的构在函数是A初始的所以输出 a1 //根据构造顺序,此时还未构造C
//当然也就没有C::fun1()
//所以输出a1
2.obj.fun() 调用父类B的fun() 调用fun1() 输出 c1 //此时已经构造了C...所以输出c1
3.析构 C的对象 调用fun2() 输出c2 //析构为构造的逆序....下同理
4.析构 B的对象 调用fun2() 即从父类A继承过来的fun2 输出a2
5.析构 A的对象 如果你在A类里写个析构函数 ~A() {cout<<"end";} 最后就会输出 end

[此贴子已经被作者于2007-3-31 20:08:28编辑过]

#6
boyyang48942007-03-31 20:19

是不是说
1.当建立对象时只是先调用该对象的类的构造函数,其他的成员函数并没有建立.只有在所有的构造函数(如:该程序)执行完之后才建立成员函数.
2.在析构时则撤消该类的所有成员函数包括构造函数

#7
游乐园2007-03-31 20:53

搞清楚类的构造和析构顺序就行了...再有就是创建对象的过程

当一个对象创建时候,他自身的数据成员在内存会分配地址,函数入口空间也会指定...

一个类的多个对象在创建时候,数据成员是自己分配自己的空间的,而函数再分配的都制的是一个入口地址

像这里继承 ,原理也是一样的 除非子类重写的父类的函数,当子类的对象析构时候,函数的入口地址也随之消失,而继承父类的函数,即使子类的对象被析构了 函数照样存在,直父类被析构位置

所以你就回忆为什么同是fun1(),而对象不同时调用的却不同

#8
boyyang48942007-03-31 21:14
这里的虚函数的作用是什么?

1.不是说基类如果定义了虚函数,那么在它的派生类中如果出现跟其定义的虚函数一样的函数(包括类型,参数类型及个数)时,用基类指针(或引用)指向派生类中该函数,则调用的是当前派生类中的函数而不是基类中被定义为虚函数的函数.

2.还有C++规定了,当一个成员函数被声明为虚函数后,其派生类中的同名函数都自动成为虚函数.

所以我总是想不通下面的问题:
class B: public A
{public:
B():A()
{fun1();}//根据2 这个也是虚函数了?下面fun()里的fun1()也是?
void fun()
{fun1();}//根据1 这个fun1()所在当前的类是类C,而不是类B,why ?难道是因为执行了main中的 obj.fun?
~B()
{fun2();}
};

[此贴子已经被作者于2007-3-31 21:20:41编辑过]

#9
游乐园2007-03-31 21:25
你说的都没有错,这个类所用到的虚函数属于静态绑定,这里看不出的作用

你可以把C类的代码的隐藏的东东也写出来就明白了


class C: public B
  {
        public:
              void fun() //继承B的,虽然隐藏但可以调用
              {fun1()};
//那这里的fun1()当然是C自己的了,所以语句obj.fun() 输出的是c1
              void fun1()
               {cout<<\"c1\";}
               void fun2()
                {cout<<\"c2\";}
               ~C()
               {fun2();}
   };


#10
boyyang48942007-03-31 21:50
明白了
那么同样的 下面这个程序:看我说的对不
#include<iostream>
using namespace std;
class A
{ public:
A(){f();}// 1 由构造顺序知先执行此函数.其中的f()指的是下面一行的f()所以最先输出a;
void f(){cout<<"a";}
};
class B:public A
{public:
B(){f();}// 2 再执行该行,其中的f()指的是下面的f()
virtual void f(){cout<<"b";} //由于函数的覆盖所以再输出b;
};
class C:public B
{public:
C(){f();}// 3 接着执行该行,其中的f()指的是下面的f()
void f(){cout<<"C";}// 由于其直接基类中的void f()定义为虚函数,所以输出的是c;
};
int main()
{
C obj;
}

所以该程序输出abc
#11
游乐园2007-03-31 21:57
呵呵 对的

其实你记得就好,在没有重写(覆盖)父类的成员函数时,派生类(继承的类)可以使用父类的函数 (当然前提都是访问权限(public或protected)可以的情况下)

但一旦重写(覆盖)的话,调用的就是自身的

你把多态那里的静态绑定和动态绑定也看看就理解的更深刻了
#12
boyyang48942007-03-31 22:01
谢谢大侠~~
#13
游乐园2007-03-31 22:06

呵呵 一起学习C++

1