gpt4 book ai didi

templates - 虚函数可以用auto参数代替吗?

转载 作者:行者123 更新时间:2023-12-02 11:29:13 24 4
gpt4 key购买 nike

此问题是 stackoverflow.com/q/2391679 的后续问题

虚拟函数的经典示例之一是

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

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

由于早期绑定(bind),后者是否更有效?

最佳答案

C++ 有两种不同的机制来编写一段代码,该代码根据所作用的对象的类型而表现不同:

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

带有 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 的某个版本,但我不知道是哪一个。但是没关系!我将生成一些代码来查看myShape 的动态类型(它实际指向的事物的类型),并使用它来查找要调用的函数。”

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

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

关于templates - 虚函数可以用auto参数代替吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50594958/

24 4 0