周四去面试,C++很长时间不用,加之C#的使用,很多基本的概念都给搞混了,根据面试的题目,看看书,写出下面的测试程序。其中包括构造函数、拷贝构造函数、析构函数、虚析构函数、动态绑定等,以注释的形式说明,不妥之处还望指正。 // COO.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <iostream.h> class Base { public: // 默认构造函数,构造函数不能定义为虚函数,因为构造函数调用时对象还未完全构造出来 Base() { cout<<"Base constructor!"<<endl; } // 拷贝构造函数 Base(const Base &baseObj) { cout<<"Base copy constructor!"<< endl; } // 将析构函数声明为虚函数,析构函数作为虚函数具有普通虚函数的一切性质 // 当删除基类指针指向的派生类对象时,如果析构函数声明为虚函数,则会自动调用派生类的析构函数 virtual ~Base() { cout<<"Delete Base obj!"<<endl; } // 虚函数 virtual void Foo() { cout<<"Call Base func Foo!"<<endl; } // 非虚函数 void Bar() { cout<<"Call Base func Bar!"<<endl; } }; class Drived : public Base { public: // 构造类时,首先调用基类的构造函数,然后执行派生类的构造函数 // 析构顺序与此相反,首先执行派生类的析构函数,然后调用基类的析构函数 Drived() { cout<<"Drived constructor!"<<endl; } // 派生类的拷贝构造函数,此处需要显示调用基类的拷贝构造函数 // 否则,将自动调用基类的默认构造函数 Drived(const Drived &drivedObj):Base(drivedObj) { cout<<"Drived copy constructor"<<endl; } ~Drived() { cout<<"Delete Drived obj!"<<endl; } // 派生类中重写虚函数 virtual void Foo() { cout<<"Call Drived func Foo!"<<endl; } // 派生类中重新定义的非虚函数 void Bar() { cout<<"Call Drived func Bar"<<endl; } }; int main(int argc, char* argv[]) { Base baseObj; Drived drivedObj; Base *pBase = &baseObj; Drived *pDrived = &drivedObj; Base *pBase1 = &drivedObj; // 动态绑定发生在运行时确定具体的调用,其它函数调用在编译时确定 // 如要发生动态绑定,需要满足是两个条件: // 1、函数必须声明为虚函数,成员函数默认为非虚函数 // 2、必须通过基类类型的引用或者指针进行函数调用 // 使用基类对象调用函数,调用的均为基类的函数,不发生动态绑定 baseObj.Foo(); baseObj.Bar(); // 使用派生类对象调用函数,调用的均为派生类的函数,不发生动态绑定 drivedObj.Foo(); drivedObj.Bar(); // 基类指针指向基类的对象,调用的为基类的函数,不发生动态绑定 pBase->Foo(); pBase->Bar(); // 派生类指针指向派生类的对象,调用派生类的函数,不发生动态绑定 pDrived->Foo(); pDrived->Bar(); // 基类指针指向派生类的对象,Foo为虚函数,调用派生类的函数,发生动态绑定 pBase1->Foo(); // 强制调用基类的函数,在编译时确定,不进行动态绑定 pBase1->Base::Foo(); // Bar不为虚函数,调用的为基类定义的函数,不发生动态绑定 pBase1->Bar(); // 此处测试析构函数,如果析构函数定义为虚函数,则删除基类指针指向的派生类时 // 发生动态绑定,执行派生类的析构函数,如果定义为非虚函数,则执行基类的析构函数 Base *pBase2= new Drived(); delete pBase2; // 此处测试拷贝构造函数,定义派生类的拷贝构造时需要显式调用基类的拷贝构造函数, // 否则调用基类的默认构造函数 Base *pBase3 = new Drived(drivedObj); delete pBase3; return 1; }