转自http://blog.youkuaiyun.com/richerg85/article/details/7592842
基本的父子类:
- #include <iostream>
- using namespace std;
- class A
- {
- public:
- A()
- {
- cout<< "A constructor" <<endl;
- }
- virtualvoid Display()
- {
- cout<<"A display"<<endl;
- }
- virtual~A()
- {
- cout<<"A discontructor"<<endl;
- }
- };
- class B:public A{
- public:
- B(int i)
- {
- m_i= i;
- cout<<"B constructor,i="<<i<<endl;
- }
- voidDisplay()
- {
- cout<<"B display"<<endl;
- }
- virtual~B()
- {
- cout<<"B disconstructor"<<endl;
- }
- private:
- intm_i;
- };
主函数调用:
测试1:
- int main()
- {
- B*a = new B(20);//直接派生类
- a->Display();
- deletea;
- }
① B *a =newB(20); 创建一个派生类对象指针,这一条语句执行,会调用
A constructor
B constructor,i=20
这符合构造函数调用顺序:先调用基类的构造函数,然后调用子类的构造函数。
② a->Display();
由于只是调用派生类B的Display函数
B display
③创建的指针对象a,不用后要删除掉:delete a; 从程序中可以看到基类A、派生类B中的析构函数前都有virtual关键字,但是在此实例中,无论析构函数前有没有virtual关键字,执行的结果都为
B disconstructor
A disconstructor
基类声明的虚函数,在派生类中也是虚函数,即使不再使用virtual关键字。
测试2(这个需要和测试进行比较看):
- int main()
- {
- A*b = new B(9);
- b->Display();
- deletea;
- }
① A *b =newB(9); 通过父类new出来子类,这一条语句执行,会调用
A constructor
B constructor,i=9
这符合构造函数调用顺序:先调用基类的构造函数,然后调用子类的构造函数。
② b->Display();由于基类A中的此函数前面有修饰符virtual,则此函数为虚函数,如果子类有同名的函数(B类中有(virtual) void Display()),则会执行子类的Display函数(即子类的函数覆盖了基类的函数)
B display
如果基类A中的Display函数去掉virtual关键字,则会执行
A display
③创建的指针对象a,不用后要删除掉:delete b; 从程序中可以看到基类A、派生类B中的析构函数前都有virtual关键字,执行的结果为
B disconstructor
A disconstructor
如果A中的virtual关键字去掉,则执行结果为
A disconstructor
基类的析构函数都必须是virtual的.
测试3:
- int main()
- {
- Bc(12);
- c.Display();
- }
此调用中,没有使用new创建对象指针,直接调用派生类的构造函数。
① B c(12);此句调用
A constructor
B constructor,i=12
和new出来的没有什么区别。
② c.Display();这个应该也没有什么疑义,和测试1中调用是一致的
B display
但是,从执行的结果来看,跟随在其后还有执行结果
B disconstructor
A disconstructor
可见,这样对象被认为是局部对象,当退出这个对象存在的范围时,会自动执行析构函数。
测试4(同理测试3):
- int main()
- {
- for(int i=0;i<2;i++)
- {
- Bc(i);
- c.Display();
- }
- }
执行结果显示为:
A constructor
B constructor,i=0
B display
B disconstructor
A disconstructor
A constructor
B constructor,i=0
B display
B disconstructor
A disconstructor