我知道关键字virtual
使基类具有多态性,如果我创建一个对象并调用virtual function
,将根据运行时分配调用相应的函数,但为什么要创建一个对象有不同的类型。我的意思是
Base *ptr = new Derived;
ptr->virtualfunction(); //calls the function which has implemented in Derived class.
如果我创建一个对象
Derived *ptr = new Derived;
ptr->virtualfunction(); // which does the same without the need of making the function virtual.
答案 0 :(得分:8)
因为您可能希望将不同类型的对象存储在一起:
std::vector<std::unique_ptr<Base>> v;
v.push_back(make_unique(new DerivedA()));
v.push_back(make_unique(new DerivedB()));
v.push_back(make_unique(new DerivedC()));
现在,如果你重新审视vector
:
for (auto& p : v) {
p->foo();
}
它将适当地调用DerivedA,B和C的foo()
。
答案 1 :(得分:2)
让我们举一个简单的例子:假设你有
class Base {};
class Derived1 : public Base {};
class Derived2 : public Base {};
现在,假设您希望能够在Derived1和Derived2实例的向量(或任何容器)中存储。 在这种情况下你必须使用基类。
std::vector<Base*>
// or std::vector<std::unique_ptr<Base>>
答案 2 :(得分:1)
对多态性的需求是需要以相同的方式处理不同的数据。不是为具有不同形状的数据集重复实现相同的算法,而是仅仅具有该算法的一个实现并且使用不同的运算符对其进行参数化不是更容易吗?
这是多态性的本质。您从算法开始,建立必须与之交互的接口,然后构建该接口的实现。在C ++中,接口的概念隐含在每个类中。任何类都暴露一个接口(尽管它可以通过其祖先支持许多接口),并且它的后代也实现它。通过使某些方法成为虚拟,后代可以覆盖并使它们适应它们自己的内部结构,而无需修改从外部操纵对象的方式。
所以多态性就是这样,可能采用不同形状的值,以及统一访问和操作它们的方法。回答问题的关键点可能是算法不知道它正在操纵哪个实现。您提供了一个简单的示例,其中代码知道它与Derived
的实例一起工作,因此可以直接调用其方法。在通用代码或引用接口的代码(可以这么说)中,该知识不存在,这迫使代码依赖于基类方法(并要求程序员确保他计划使用该代码的类)很明确 - 即虚拟 - 需要的地方。)
多态性有许多有用的应用,但它们都源于上述原则:
仅举几例。请注意,编译时多态(模板)和运行时多态(virtual
方法和继承)都实现了这一目标,尽管方式不同,并且具有不同的优缺点。