C++的继承和多态是面试经常会问的问题,菱形继承问的会少一点,但是问到了还是知道些的好。
一、正常单继承
对于正常的单继承,可以看到多态的实现,父类指针指向孙子类对象:
class A {
public:
virtual void foo() { cout << "A foo()" << endl; }
};
class B :public A {
void foo() override { cout << "B foo()" << endl; }
};
class D : public B {
void foo() override { cout << "D foo()" << endl; }
};
int main() {
A* pb = new B();
pb->foo(); // "B foo()"
A* pd = new D();
pd->foo(); // "D foo()"
D d;
// d.foo(); // Error: Member is inaccessible
}
这样的继承下,多态不仅能用父类指针指向不同的对象,还可以访问到对象的私有成员函数。
二、简单菱形继承
为了演示方便,使用如下四个类构成的菱形继承:
类关系如下:
class A {
public:
virtual void foo() { cout << "A foo()" << endl; }
};
class B :public A {
public:
void foo() override { cout << "B foo()" << endl; }
};
class C :public A {
public:
void foo() override { cout << "C foo()" << endl; }
};
class D : public B, public C {
};
int main() {
D d;
// d.foo(); // Error: 对 "foo" 的访问不明确
// d.A::foo(); // Error: 对 "A" 的访问不明确
d.B::foo(); // "B foo()"
d.C::foo(); // "C foo()"
A* pb = new B();
pb->foo(); // "B foo()"
A* pc = new C();
pc->foo(); // "C foo()"
// A* pd = new D(); // Error: 从 "D *" 到 "A *" 的转换不明确
}
可以看到,B 和 D,C 和 D 之间的关系是没有问题的,但是 A 和 D 之间的关系就不明确了,虚继承,就是将分叉的两个类,继承时加上 virtual,如下:
class A {
public:
virtual void foo() { cout << "A foo()" << endl; }
};
class B : virtual public A { // newly added
public:
void foo() override { cout << "B foo()" << endl; }
};
class C : virtual public A { // newly added
public:
void foo() override { cout << "C foo()" << endl; }
};
class D : public B, public C {
public:
void foo() override { cout << "D foo()" << endl; } // 一定要override,不然会Error
};
int main() {
D* pad = new D(); // ++ 注意是D* ++
pad->foo(); // "D foo()"
pad->A::foo(); // "A foo()"
pad->B::foo(); // "B foo()"
pad->C::foo(); // "C foo()"
pad->D::foo(); // "D foo()"
}