工程上的多继承
- 被实际开发经验抛弃的多继承;
- 工程开发中真正意义上的多继承是几乎不被使用的;
- 多继承带来的代码复杂性远多于其带来的便利;
- 多继承对代码维护上的影响是灾难性的;
- 在设计方法上,任何多继承都可以用但继承代替
多继承的二义性和无法解决的问题
- 多继承的二义性:用声明虚基类解决
#include <iostream>
//将B声明为虚基类,由C类的对象访问B类成员不会产生二义性
class B
{
public:
int b;
B():b(0){std::cout << "调用了构造函数B()" << std::endl;}
};
class B1 : virtual public B//声明为虚基类
{
public:
int b1;
B1():b1(0){std::cout << "调用了构造函数B1()" << std::endl;}
};
class B2 : virtual public B//声明为虚基类
{
public:
int b2;
B2():b2(0){std::cout << "调用了构造函数B2()" << std::endl;}
};
class C : public B1, public B2
{
public:
int c;
C():c(0){std::cout << "调用了构造函数C()" << std::endl;}
};
int main()
{
C my_c;
my_c.b = 10;
std::cout << "B::b = " << my_c.b << std::endl;
return 0;
}
执行结果:
可以看出,定义一个C类对象,会调用一次B类的构造函数B()。若去掉 virtual 关键字,即程序为:
#include <iostream>
class B
{
public:
int b;
B():b(0){std::cout << "调用了构造函数B()" << std::endl;}
};
class B1 : public B//声明为虚基类
{
public:
int b1;
B1():b1(0){std::cout << "调用了构造函数B1()" << std::endl;}
};
class B2 : public B//声明为虚基类
{
public:
int b2;
B2():b2(0){std::cout << "调用了构造函数B2()" << std::endl;}
};
class C : public B1, public B2
{
public:
int c;
C():c(0){std::cout << "调用了构造函数C()" << std::endl;}
};
int main()
{
C my_c;
return 0;
}
执行结果为:
调用了两次B类的构造函数,且访问B类的数据成员b时,会产生二义性。
- 多继承中无法解决的问题
看如下程序:
#include <iostream>
class B1
{
public:
int b;
B1():b(0){std::cout << "调用了构造函数B1()" << std::endl;}
};
class B2
{
public:
int b;
B2():b(0){std::cout << "调用了构造函数B2()" << std::endl;}
};
class C : public B1, public B2
{
public:
int c;
C():c(0){std::cout << "调用了构造函数C()" << std::endl;}
};
int main()
{
C my_c;
my_c.b = 10;
return 0;
}
产生错误:
产生二义性。
抽象类在多继承中的应用
- 一个派生类继承于两个抽象基类,即使这两个抽象基类有相同的成员函数,只要将其声明为纯虚函数,就不会产生二义性。程序如下:
#include <iostream>
class Interface1
{
public:
virtual void add(int, int) = 0;
virtual void print() = 0;
};
class Interface2
{
public:
virtual void mult(int, int) = 0;
virtual void print() = 0;
};
class Parent
{
public:
void display()
{
std::cout << "Parent::display()执行" << std::endl;
}
};
class Child : public Parent, public Interface1, public Interface2
{
public:
virtual void add(int a, int b)
{
std::cout << "Child::add(int, int)执行" << std::endl;
std::cout << "a = " << a << "; "
<< "b = " << b << "; "
<< "a + b = " << a + b << std::endl;
}
virtual void mult(int a, int b)
{
std::cout << "Child::mult(int, int)执行" << std::endl;
std::cout << "a = " << a << "; "
<< "b = " << b << "; "
<< "a * b = " << a * b << std::endl;
}
virtual void print()
{
std::cout << "Child::print()执行" << std::endl;
}
};
int main()
{
Child ch;
ch.print();
ch.display();
Interface1 * inter1 = &ch;
Interface2 * inter2 = &ch;
inter1->add(1, 2);
inter1->print();
inter2->mult(2, 3);
inter2->print();
return 0;
}
执行结果:
即使两个抽象基类 Interface1 和 Interface2 都有 print() 成员函数(纯虚函数),也没有产生二义性。