Wednesday, March 28, 2007

Virtual inheritance

Since the C++ adopt the inheritance policy that admit one class have multiple super-class, so the constructor of the derived class in the diamond class-inheritance becomes a problem for it would be create two same object if you use the common class inheritance policy.

For example:
引用:
"在标准I/O库中的类都继承了一个共同的抽象基类ios,那个抽象基类管理流的条件状态并保存流所读写的缓冲区。istream和ostream类直接继 承这个公共基类,库定义了另一个名为isotream的类,它同时继承istream和ostream,iostream类既可以对流进行读又可以对流进 行写。如果I/O类型使用常规继承,则每个iostream对象可能包含两个ios子对象:一个包含在它的istream子对象中,另一个包含在它的 ostream子对象中。从设计角度讲,这个实现是错误的:iostream类想要对单个缓冲区进行读和写,它希望跨越输入和输出操作符共享条件状态。
在C++中,通过使用虚继承(virtual inheritance)解决这类问题。虚继承是一种机制,类通过虚继承指出它希望共享其虚基类的状态。在虚继承下,对给定虚基类,无论该类在派生层次中作为虚基类出现多少次,只继承一个共享的基类子对象。共享的基类子对象称为虚基类(virtual base class)
通过在派生类列表中包含关键字virtual设置虚基类,例如:
class istream : public virtual ios {...};
class ostream : virtual public ios {...};
class iostream : public istream, public ostream {...};
假定通过多个派生路径继承名为X的成员,有下面三种可能性:
1)如果在每个路径中X表示同一虚基类成员,则没有二义性,因为共享该成员的单个实例;
2)如果在某个路径中X是虚基类的成员,而在另一路径中X是后代派生类的成员,也没有二义性――特定派生类实例的优先级高于共享虚基类实例。
3)如果沿每个继承路径X表示后代派生类的不同成员,则该成员的直接访问是二义性的。
"

The Virtual inheritance is the solution to this problem:

class B {
public:
void print() {
std::cout << "B" << std::endl;
}
};

class D1: public virtual B {
};

class D2: public virtual B {
public:
void print() {
std::cout << "D2" << std::endl;
}
};

class DD: public D1, public D2 {
};

int main () {
DD d;
d.print(); // ok: call D2::print
return 0;
}

No comments: