引出
在使用多态时,可能会发生由静态联编(静态绑定)导致的父类引用或指针调用子类重写方法,实际调用结果为父类中方法,但是静态联编可用使用虚函数来解决,从而恢复多态
静态绑定的方法调用在编译时就指定了其调用方法,此时就算是使用向上类型转换(子类的对象),受到调用的依旧是基类方法
多态是指:父类的引用或指针指向子类对象,从而使用一个基类下多个子类的重写方法
#include <iostream>
using namespace std;
//基类
class Base{
public:
void printError(){ //使用virtual关键字声明函数,将其变为虚函数,即可使用多态
cout << "基类方法!" << endl;
};
};
//派生类
class Derived : public Base{
public:
void printError(){
cout << "派生类方法!" << endl;
}
};
void test()
{
Base *ex = new Derived(); //静态联编导致子类对象调用基类方法,而不是子类方法
ex->printError(); //输出基类方法!
}
int main()
{
test();
return 0;
}
对象切割
对象切割与静态联编相似,对象切割也会导致调用的方法变为基类方法,但对象切割并不是静态联编导致的,也不能通过虚函数解决
#include <iostream>
using namespace std;
//基类
class Base{
public:
virtual void printError(){ //对象切片无法使用virtual关键字声明虚函数解决
cout << "基类方法!" << endl;
};
};
//派生类
class Derived : public Base{
public:
void printError(){
cout << "派生类方法!" << endl;
}
};
void test()
{
Base e = Derived(); //对象切片导致子类对象调用基类方法,而不是子类方法
ex.printError(); //输出基类方法!
}
int main()
{
test();
return 0;
}
产生原因
当把一个派生类对象
赋给一个基类对象
时(并不是使用父类指针或引用接收子类对象),会发生对象切割。(另外用基类对象强制转换派生类对象也会)
接收值传递的返回值时,发生的拷贝构造也会发生对象切割
发生对象切片后派生类的覆盖部分就被切掉了,所以调用的方法将会是父类方法