class A { public: int iValue; }; class B:public A { public: void bPrintf(){cout<<"This is class B"<<endl;}; }; class C:public A { public: void cPrintf(){cout<<"This is class C"<<endl;}; }; class D:public B,public C { public: void dPrintf(){cout<<"This is class D"<<endl;}; }; void main() { D d; cout<<d.iValue<<endl; //错误,不明确的访问 cout<<d.A::iValue<<endl; //正确 cout<<d.B::iValue<<endl; //正确 cout<<d.C::iValue<<endl; //正确 } 从代码中可以看出类B C都继承了类A的iValue成员,因此类B C都有一个成员变量iValue ,而类D又继承了B C,这样类D就有一个重名的成员 iValue(一个是从类B中继承过来的,一个是从类C中继承过来的).在主函数中调用d.iValue 因为类D有一个重名的成员iValue编译器不知道调用 从谁继承过来的iValue所以就产生的二义性的问题.正确的做法应该是加上作用域限定符 d.B::iValue 表示调用从B类继承过来的iValue。不过 类D的实例中就有多个iValue的实例,就会占用内存空间。所以C++中就引用了虚基类的概念,来解决这个问题。 class A { public: int iValue; }; class B:virtual public A { public: void bPrintf(){cout<<"This is class B"<<endl;}; }; class C:virtual public A { public: void cPrintf(){cout<<"This is class C"<<endl;}; }; class D:public B,public C { public: void dPrintf(){cout<<"This is class D"<<endl;}; }; void main() { D d; cout<<d.iValue<<endl; //正确 } 在继承的类的前面加上virtual关键字表示被继承的类是一个虚基类,它的被继承成员在派生类中只保留一个实例。例如iValue这个成员,从类 D这个角度上来看,它是从类B与类C继承过来的,而类B C又是从类A继承过来的,但它们只保留一个副本。因此在主函数中调用d.iValue时就不 会产生错误。
声明指向类的指针时,不管引用的实例是哪个类的, 当你调用的时候系统会调用左值那个对象所属类的方法
class A { public: void funPrint(){cout<<"funPrint of class A"<<endl;}; }; class B:public A { public: void funPrint(){cout<<"funPrint of class B"<<endl;}; }; void main() { A *p; //定义基类的指针 A a; B b; p=&a; p->funPrint(); p=&b; p->funPrint(); } 答案是funPrint of class A 与 funPrint of class A 因为p是一个A类的指针,所以不管你将p指针指向类A或是类B,最终调用的函数都是类A的funPrint 函数。这就是静态联篇,编译器在编译的时候就已经确定好了 如果我想实现跟据实例的不同来动态决定调用哪个函数呢?这就须要用到 虚函数(也就是动态联篇) 在基类的成员函数前加virtual关键字表示这个函数是一个虚函数,所谓虚函数就是在编译的时候不确定要调用哪个函数,而是动态决定将要调 用哪个函数,要实现虚函数必须派生类的函数名与基类相同,参数名参数类型等也要与基类相同。但派生类中的virtual关键字可以省略,也表 示这是一个虚函数 class A { public: virtual void funPrint(){cout<<"funPrint of class A"<<endl;}; }; class B:public A { public: virtual void funPrint(){cout<<"funPrint of class B"<<endl;}; }; void main() { A *p; //定义基类的指针 A a; B b; p=&a; p->funPrint(); p=&b; p->funPrint(); } funPrint of class A funPrint of class B
用C++开发的时候,用来做基类的类的析构函数一般都是虚函数
这样做是为了当用一个基类的指针删除一个派生类的对象时,派生类的析构函数会被调用。
并不是要把所有类的析构函数都写成虚函数。因为当类里面有虚函数的时候,编译器会给类添加一个虚函数表,里面来存放虚函数指针,这样就会增加类的存储空间。
所以,只有当一个类被用来作为基类的时候,才把析构函数写成虚函数。
class ClxBase { public: ClxBase() {}; virtual ~ClxBase() {}; virtual void DoSomething() { cout << "Do something in class ClxBase!" << endl; }; }; class ClxDerived : public ClxBase { public: ClxDerived() {}; ~ClxDerived() { cout << "Output from the destructor of class ClxDerived!" << endl; }; void DoSomething() { cout << "Do something in class ClxDerived!" << endl; }; }; ClxBase *pTest = new ClxDerived; pTest->DoSomething(); delete pTest;