当多态遇见对象数组会发生什么?
多态:一个指针,通过这个指针指向一个对象之后,究竟我们这个指针调用的函数是父类的版本还是子类的版本?依赖于实际指向的对象是父类对象还是子类对象。
当多态遇到对象数组后:
程序会爆掉
不要将多态应用于数组
-
指针运算是通过指针的类型进行的
-
多态通过虚函数表实现的
多态与指针运算玩混搭的后果
为什么没有讲解多重继承?
C++在语法上直接支持多重继承
被实际开发经验抛弃的多继承
-
工程开发中真正意义上的多继承是几乎不被使用的
-
多重继承带来的代码复杂性远多于其带来的便利
-
多重继承对代码维护性上的影响是灾难性的
-
在设计方法上,任何多继承都可以用单继承代替
多继承复杂性示例(不用多继承!!)
class Object
{
protected:
int d;
};
class P1 : public Object
{
protected:
int i;
};
class P2 : public Object
{
protected:
int j;
};
class Child : public P1, public P2
{
public:
Child(int i, int j)
{
//this->d = 0;//错误,有歧义;同时继承p1,p2,间接继承obj,不知道obj中的d来自哪里
this->i = i;
this->j = j;
}
};
-
在只有单继承的系统中,类之间的继承关系为一颗树。
-
在引入多重继承的系统中,类之间的继承关系呈现为一张图。
C++中对多继承二义性的解决方案
虚继承:
为了解决从不同途径继承来的同名数据成员造成的二义性问题,可以将共同基类设置为虚基类。这时从不同的路径继承过来的同名数据成员在内存中就只有一个拷贝。
虚继承会导致大量性能上的开销,用不用得到还不一定。因此最好少用虚继承,不用多继承,不用多继承,不用多继承
C++是否有Java中接口的概念?
(单继承+接口去替代多继承)
-
绝大多数面向对象语言都不支持多继承
-
绝大多数面向对象语言都支持接口的概念
-
C++中没有接口的概念
-
C++中可以使用纯虚函数实现接口
接口类中只有函数原型定义,没有任何数据的定义。
实际工程经验证明
-
多重继承接口不会带来二义性和复杂性等问题
-
多重继承可以通过精心设计用单继承和接口来代替
接口类只是一个功能说明,而不是功能实现。子类需要根据功能说明定义功能实现。
接口使用示例
#include <cstdlib>
#include <iostream>
using namespace std;
class Interface1
{
public:
virtual void print() = 0;
virtual int add(int i, int j) = 0;
/*
接口只是功能的说明
单从函数原型来看,两个add函数是一模一样的(外型、功能)
在子类里面,只需要实现一份即可
因此下面调用的c.add调用没有任何二义性
*/
};
struct Interface2//为了表明不会出现二义性,引入这个
{
virtual int add(int i, int j) = 0;
virtual int minus(int i, int j) = 0;
};
class Child : public Interface1, public Interface2
{
public:
void print()
{
cout<<"Child::print"<<endl;
}
int add(int i, int j)
{
return i + j;
}
int minus(int i, int j)
{
return i - j;
}
};
int main(int argc, char *argv[])
{
Child c;
c.print();
cout<<c.add(3, 5)<<endl;//使用多重继承,但是没有引起二义性
cout<<c.minus(4, 6)<<endl;
Interface1* i1 = &c;//赋值兼容性原则
Interface2* i2 = &c;//赋值兼容性原则
cout<<i1->add(7, 8)<<endl;//调用的接口1的add
cout<<i2->add(7, 8)<<endl;//调用的接口2的add
cout << "Press the enter key to continue ...";
cin.get();
return EXIT_SUCCESS;
}
result:
Child::print
8
-2
15
15
Press the enter key to continue ...