【问题标题】:Can virtual functions be replaced with auto parameters?虚函数可以用自动参数代替吗?
【发布时间】:2018-05-30 00:56:32
【问题描述】:

这个问题跟进stackoverflow.com/q/2391679

virtual 函数的经典示例之一是

class Shape
{
public:
    virtual string draw() = 0;
};

class Circle : public Shape
{
public:
    string draw() { return "Round"; }
};

class Rectangle : public Shape
{
public:
    string draw() { return "Flat"; }
};

void print (Shape& obj)
{
    cout << obj.draw();
}

但是,我们可以在 C++ 14 中传递 auto 参数

class Circle
{
public:
    string draw() { return "Round"; }
};

class Rectangle
{
public:
    string draw() { return "Flat"; }
};

void print (auto& shape)
{
    cout << shape.draw();
}

我们什么时候应该更喜欢virtual 函数或auto 参数?

由于早期绑定,后者更有效吗?

【问题讨论】:

  • @vu1p3n0x 这个问题不能重复;它根本没有提到auto
  • 继承的(主要)目的是子类型化。没有其他子类型化功能。

标签: templates polymorphism c++14 virtual-functions auto


【解决方案1】:

C++ 有两种不同的机制来编写一段代码,这些代码的行为会根据所作用对象的类型而有所不同:

  • virtual 函数和继承,在运行时工作,并且
  • 模板函数,在编译时工作。

带有auto 参数的示例(显然是weren't actually adopted in C++14 except for lambda functions)适用于模板。你写的代码相当于

template <typename T>
void print(T& shape) {
    cout << shape.name();
}

此代码假定T 的类型可以在编译时确定,因为编译器需要知道T 的类型才能填写模板。一旦编译器知道这一点,它就可以说“啊,我知道那个类型是什么!我将生成代码以直接调用该类型的name 函数,并且我确切地知道将调用什么函数。”

另一方面,虚函数和继承在运行时工作。例如,假设您要编写一个从网络读取一些数据的函数,然后返回CircleRectangle。你可能有一些这样的代码:

Shape* myShape = decodeNetworkData();

在这里,编译器只知道myShape 指向某种Shape,但它无法判断这是圆形还是方形。因此,如果您要调用

cout << myShape->name();

然后编译器会说“我知道你在调用name 的某个版本,但我不知道是哪个版本。不过没关系!我将生成一些查看@987654336 的动态类型的代码@(它实际指向的事物的类型)并使用它来查找要调用的函数。”

请注意,编译器在每种情况下生成的代码是不同的,行为也会不同。在第一种情况下,编译器确切地知道要调用哪个函数。其次,编译器不知道要调用什么函数,必须生成一些额外的代码才能使事情正常工作。但是,另一方面,如果您没有具有虚拟 name 函数的 Shape 类型,则可以使“解码网络字节”代码 sn-p 与您的第一个函数一起使用,因为编译器必须提前知道它将通过网络看到什么类型。

有人建议将此问题标记为a duplicate of this older question on templates and inheritance,尽管它表面上不是同一个问题。一旦您知道auto 在此上下文中的关键字意味着“这实际上是一个模板函数”,您就可以查看其他提出的问题以获取一些关于 静态多态性 之间差异的额外示例(与模板)和运行时多态(带有虚函数)。

【讨论】:

  • 简而言之,auto 在编译时被揭开神秘面纱,因此编译器知道在每次调用时将什么类型引入函数吗?
  • 我知道virtual函数的早期绑定和后期绑定(即静态与运行时多态性)的区别,但不知道auto是使用早期绑定还是后期绑定,这是整体这个问题的重点。这就是为什么它不是重复的。
  • 没有模板关键字的模板?这对我来说很新鲜,而且很丑!
猜你喜欢
  • 2018-08-05
  • 2011-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-27
  • 2018-10-06
  • 2016-02-05
  • 2013-10-12
相关资源
最近更新 更多