templates - Can virtual functions be replaced with auto parameters?
问题描述
This question follows up on stackoverflow.com/q/2391679
One of the classic examples of virtual
functions is
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();
}
However, we can instead pass an auto
parameter in C++ 14
class Circle
{
public:
string draw() { return "Round"; }
};
class Rectangle
{
public:
string draw() { return "Flat"; }
};
void print (auto& shape)
{
cout << shape.draw();
}
When should we prefer virtual
functions or auto
parameters?
Is the latter more efficient due to early binding?
解决方案
C++ 有两种不同的机制来编写一段代码,这些代码的行为根据所作用的对象的类型而有所不同:
virtual
在运行时工作的函数和继承,以及- 模板函数,在编译时工作。
您的带有auto
参数的示例(除了 lambda 函数,显然在 C++14 中实际上并未采用)适用于模板。你写的代码相当于
template <typename T>
void print(T& shape) {
cout << shape.name();
}
此代码假定T
可以在编译时确定类型,因为编译器需要知道类型T
才能填写模板。一旦编译器知道这一点,它就可以说“啊,我知道那个类型是什么!我将生成代码以直接调用该name
类型的函数,并且我确切地知道将调用什么函数。”
另一方面,虚函数和继承在运行时工作。例如,假设您要编写一个从网络读取一些数据的函数,然后返回 aCircle
或 a Rectangle
。你可能有一些这样的代码:
Shape* myShape = decodeNetworkData();
在这里,编译器只知道myShape
指向某种Shape
,但它无法判断那是圆形还是方形。因此,如果你打电话
cout << myShape->name();
然后编译器会说“我知道你在调用某个版本name
,但我不知道是哪个版本。但这没关系!我将生成一些查看动态类型的代码myShape
(它实际上是指向)并使用它来查找要调用的函数。”
请注意,编译器在每种情况下生成的代码是不同的,行为也会不同。在第一种情况下,编译器确切地知道要调用哪个函数。其次,编译器不知道要调用什么函数,并且必须生成一些额外的代码才能使事情正常进行。但是,另一方面,如果您没有具有Shape
虚name
函数的类型,则可以使“解码网络字节”代码片段与您的第一个函数一起使用,因为编译器必须提前知道,它将通过网络看到什么类型。
有人提议将此问题标记为有关模板和继承的旧问题的重复,即使它表面上不是同一个问题。一旦您知道auto
此上下文中的关键字意味着“这确实是一个模板函数”,您就可以查看其他提出的问题,以获得静态多态性(使用模板)和运行时多态性(使用虚函数)之间差异的一些额外示例.
推荐阅读
- sql - 实体框架的 SQL 连接超时错误
- swift - 从远程 URL 保存音频文件并在 APlayer 中本地加载它们
- python - 将 Curl 命令转换为 python
- python - OpenCV findcontour矩形创建错误
- facebook-javascript-sdk - 最近的 facebook api 更改后如何发布到用户时间轴?
- keras - 在 PyTorch 中准备序列到序列网络的解码器
- json - Angular 2 及更高版本 | 从json中提取属性
- c - 将 char* 分配给 char
- c - 将值安全分配给C中的位域
- angular - 在离子应用程序中为信标添加一些安全性