从我目前学到的知识来看,有两种多态性,编译时和运行时。在编译时,多态函数或运算符由编译器解析,而在运行时,它在运行时解析。编译时多态性的示例包括函数和运算符重载,运行时多态性包括函数覆盖和虚函数。此外,还有像早期绑定和晚期绑定这样的情况,我稍后会谈到。考虑以下代码:
class base {
public:
void Print() {
std::cout << "This is parent class\n";
}
};
class derived : public base {
public:
void Print() {
std::cout << "This is derived class\n";
}
};
如果我这样做:
base b1;
b1.Print();
derived d1;
d1.Print();
结果很明显:
This is parent class
This is derived class
当我使用指向基类的指针来操作这些函数时,真正的问题就开始了。
base b1;
derived d1;
base* pb = &b1;
base* pb2 = &d1;
pb->Print();
pb2->Print();
输出将是:
This is parent class
This is parent class
这是由于早期绑定,编译器检查调用函数的对象类型,而不是其处理的对象类型。很明显它是在编译时完成的。现在,如果我virtual
在基类函数定义中使用关键字,那么我可以轻松地完成上述操作,这是由于后期绑定,它根据对象的类型为运行时保存了函数定义。这是运行时多态的一个例子。
抱歉花了太长时间,我的问题是,这是我们实现运行时多态性的唯一方法吗?此外,如果函数覆盖是运行时多态,那么前面的示例(即具有早期绑定的例子)也应该是运行时多态,因为它也在执行函数覆盖。