3

我知道关键字virtual使基类具有多态性,如果我创建一个对象并调用 a 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.
4

3 回答 3

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();
}

它将foo()适当地调用 DerivedA、B 和 C。

于 2013-06-28T11:15:09.337 回答
2

Let's go with a simple example : Let's say you have

class Base {};
class Derived1 : public Base {};
class Derived2 : public Base {};

Now, let's say you want to be able to store in a vector (or any container) both Derived1 and Derived2 instances. You have to use the base class in that case.

std::vector<Base*>
// or std::vector<std::unique_ptr<Base>>
于 2013-06-28T11:16:21.980 回答
1

对多态性的需求是需要以相同的方式处理不同的数据。与其对具有不同形状的数据集一遍又一遍地重新实现相同的算法,不如只使用该算法的一种实现并使用不同的运算符对其进行参数化不是更容易吗?

这就是多态的本质。您从一个算法开始,建立它必须与之交互的接口,然后构建该接口的实现。在 C++ 中,接口的概念隐含在每个类中。任何类都公开一个接口(尽管它可能通过其祖先支持许多接口),并且它的后代也实现它。通过使某些方法虚拟化,后代可以覆盖并调整它们以适应它们自己的内部结构,而无需修改从外部操作对象的方式。

所以多态性就是这样,可以采用不同形状的值,以及统一访问和操作它们的方法。回答您的问题的关键点可能是该算法不知道它正在操纵哪个实现。您提供了一个简单的示例,其中代码知道它与 的实例一起使用Derived,因此可以直接调用其方法。在通用代码或引用接口的代码(可以这么说)中,不存在该知识,这迫使代码依赖于基类方法(并要求程序员确保他计划与该代码一起使用的类定义明确 - 即虚拟 - 在需要的地方)。

多态性有很多有用的应用,但它们都源于上述原理:

  • 异构数据集(如其他答案所示),
  • 注入(其中同一接口的不同实现可以在运行时相互交换),
  • 测试(更具体地说是模拟,其中与给定类 C 交互的类被替换为有助于测试 C 正确行为的假人),

仅举几例。请注意,编译时多态性(模板)和运行时多态性(virtual方法和继承)都实现了该目标,尽管方式不同,优缺点也不同。

于 2013-06-28T13:30:56.740 回答