如果沿每个继承路径 X 表示后代派生类的不同成员,则该成员的直接访问是二义性的。 Code
Code1:覆盖虚函数机制
Item_base *baseP = &derived;
//calls version from the base class regardless of the dynamic type of baseP
double d = baseP->Item_base::net_price(42);
Code2:虚析构函数
/*如果析构函数为虚函数,那么通过指针调用时,运行哪个析构函数将因指针所指对象类型的不同而不同:*/
Item_base *itemP = new Item_base; // same static and dynamic type
delete itemP; // ok: destructor for Item_base called
itemP = new Bulk_item; // ok: static and dynamic types differ
delete itemP; // ok: destructor for Bulk_item called
Code3:虚函数必须在基类和派生类中拥有同一原型
class Base {
public:
virtual int fcn();
};
class D1 : public Base {
public:
// hides fcn in the base; this fcn is not virtual
int fcn(int); // parameter list differs from fcn in Base
// D1 inherits definition of Base::fcn()
};
class D2 : public D1 {
public:
int fcn(int); // nonvirtual function hides D1::fcn(int)
int fcn(); // redefines virtual fcn from Base
};
/*D1 中的 fcn 版本没有重定义 Base 的虚函数 fcn,相反,它屏蔽了基类的 fcn。结果 D1 有两个名 为 fcn 的函数:类从 Base 继承了一个名为 fcn 的虚 函数,类又定义了自己的名为 fcn 的非虚成员函 数,该函数接受一个 int 形参。 但是,从 Base 继承的虚函数不能通过 D1 对象(或 D1 的引用或指针) 调用, 因为该函数被 fcn(int) 的定义屏蔽了。
类 D2 重定义了它继承的两个函数,它重定义了 Base 中定义的 fcn 的原始版本并重定义了 D1 中定义 的非虚版本。*/ Code4:通过基类调用被屏蔽的虚函数
Base bobj; D1 d1obj; D2 d2obj;
Base *bp1 = &bobj, *bp2 = &d1obj, *bp3 = &d2obj;
bp1->fcn();
bp2->fcn();
bp3->fcn();
// ok: virtual call, will call Base::fcnat run time // ok: virtual call, will call Base::fcnat run time // ok: virtual call, will call D2::fcnat run time
三个指针都是基类类型的指针,因此通过在 Base 中查找 fcn 来确定这三 个调用,所以这些调用是合法 的。另外,因为 fcn 是虚函数,所以编译器会生成代码,在运行时基于引用指针所绑定的对象的实际类型进 行调用。在 bp2 的情况,基本对象是 D1 类的,D1 类没有重定义不接受实参的虚函数版本,通过 bp2 的 函数调用(在运行时)调用 Base 中定义的版本。
Code5:虚继承
/*每个 IO 库类都继承了一个共同的抽象基类,那个抽象基类管理流的条件状态并保存流所读写的缓冲区。 istream 和 ostream 类直接继承这个公共基类,库定义了另一个名为 iostream 的类,它同时继承 istream 和 ostream,iostream 类既可以对流进行读又可以对流进行写。
我们知道,多重继承的类从它的每个父类继承状态和动作,如果 IO 类 型使用常规继承,则每个 iostream 对象可能包含两个 ios 子对象:一个包含 在它的 istream 子对象中,另一个包含在它的 ostream 子对 象中,从设计角度讲,这个实现正是错误的:iostream 类想要对单个缓冲区进行读和写,它希望跨越输入和输 出操作符共享条件状态。如果有两个单独的 ios 对象,这种共享是不可能的。
在 C++ 中,通过使用虚继承解决这类问题。*/
class istream : public virtual ios { ... };
class ostream : virtual public ios { ... };
// iostream inherits only one copy of its ios base class
class iostream: public istream, public ostream { ... };
From:
http://blog.csdn.net/liufei_learning/article/details/22708639