从我到目前为止学到的,有两种多态,编译时和运行时。 在编译时,多态函数或运算符由编译器解析,而在运行时,它在运行时解析。 compiile time polymorphism的示例包括函数和运算符重载,运行时多态包括函数重写和虚函数。 另外还有像早期绑定和后期绑定这样的情况,我将在稍后介绍。 请考虑以下代码:
for i, e in enumerate(lst):
if e == search_value:
lst.insert(i+1, value)
如果我这样做:
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();
这是由于Early binding,编译器检查调用该函数的对象的类型,而不是它处理的对象的类型。而且很明显它是在编译时完成的。现在,如果我在基类函数定义中使用This is parent class
This is parent class
关键字,那么我可以轻松地完成上述操作而不会有任何麻烦,这是由于后期绑定,它根据对象的类型保存运行时的函数定义处理。这是运行时多态性的一个例子。
抱歉花了太长时间,我的问题是,这是我们实现运行时多态性的唯一方法吗?此外,如果函数重写是运行时多态性,那么前面的示例(即具有早期绑定的示例)也应该是运行时多态性,因为它也在执行函数重写。
答案 0 :(得分:0)
没有什么会强迫您使用虚函数来实现运行时多态性。在性能关键代码中,经常会看到这样的事情,以避免虚函数调用的成本:
void foo(Base * _b)
{
if(_b->typeID == TID_BASE)
{
b->bar();
}
else if(_b->typeID == TID_DERIVED)
{
static_cast<Derived*>(_b)->bar();
}
}
其中type id是某种形式的枚举或唯一标识类型的指针。也就是说,我永远不会建议这样做,除非你实际测量到它在你的情况下会产生性能差异。
关于你的上一个问题。不,这绝不是后期绑定,因为你根本没有覆盖任何功能。在您的示例中,Print
类中有一个Base
函数,Derived
类中有一个Base
函数。通过将您的对象转换为Base
,您明确请求Print
类mvn dependency:tree
函数。