虚函数可以用自动参数代替吗?
Can virtual functions be replaced with auto parameters?
这个问题跟进 whosebug.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
参数?
后者是否由于提前绑定而更高效?
C++ 有两种不同的机制来编写一段代码,这些代码根据所作用的对象的类型表现不同:
virtual
函数和继承,它们在 运行时 和 工作
- 模板函数,在编译时工作。
带有 auto
参数的示例(显然 )适用于模板。您编写的代码相当于
template <typename T>
void print(T& shape) {
cout << shape.name();
}
此代码假定 T
的类型可以在编译时 确定 ,因为编译器需要知道 T
的类型顺序填写模板。一旦编译器知道这一点,它就可以说 "Ah, I know what that type is! I'll generate code to directly call the name
function in that type, and I know exactly what function that will call."
另一方面,虚函数和继承在运行时起作用。例如,假设您要编写一个从网络读取一些数据的函数,然后返回 Circle
或 Rectangle
。您可能有这样的代码:
Shape* myShape = decodeNetworkData();
在这里,编译器只知道 myShape
指向某种 Shape
,但它无法判断那是圆形还是方形。因此,如果您要调用
cout << myShape->name();
然后编译器会说 "I know you're calling some version of name
, but I don't know which one. But that's okay! I'll generate some code that looks at the dynamic type of myShape
(the type of the thing it actually points at) and uses that to look up which function to call."
请注意,编译器在每种情况下生成的代码都不同,行为也会不同。在第一种情况下,编译器确切地知道要调用哪个函数。在第二种情况下,编译器不知道要调用什么函数,必须生成一些额外的代码才能运行。但是,另一方面,如果您没有带有虚拟 name
函数的 Shape
类型,您可以使 "decode the bytes of the network" 代码片段与您的第一个函数一起使用,因为编译器必须提前知道它将通过网络看到什么类型。
有人建议将此问题标记为 a duplicate of this older question on templates and inheritance,即使它在表面上不是同一个问题。一旦您知道此上下文中的 auto
关键字表示 "this is really a template function," 您可以查看其他提出的问题以获得 静态多态性 之间差异的其他示例(使用模板)和运行时多态性(使用虚函数)。
这个问题跟进 whosebug.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
参数?
后者是否由于提前绑定而更高效?
C++ 有两种不同的机制来编写一段代码,这些代码根据所作用的对象的类型表现不同:
virtual
函数和继承,它们在 运行时 和 工作
- 模板函数,在编译时工作。
带有 auto
参数的示例(显然
template <typename T>
void print(T& shape) {
cout << shape.name();
}
此代码假定 T
的类型可以在编译时 确定 ,因为编译器需要知道 T
的类型顺序填写模板。一旦编译器知道这一点,它就可以说 "Ah, I know what that type is! I'll generate code to directly call the name
function in that type, and I know exactly what function that will call."
另一方面,虚函数和继承在运行时起作用。例如,假设您要编写一个从网络读取一些数据的函数,然后返回 Circle
或 Rectangle
。您可能有这样的代码:
Shape* myShape = decodeNetworkData();
在这里,编译器只知道 myShape
指向某种 Shape
,但它无法判断那是圆形还是方形。因此,如果您要调用
cout << myShape->name();
然后编译器会说 "I know you're calling some version of name
, but I don't know which one. But that's okay! I'll generate some code that looks at the dynamic type of myShape
(the type of the thing it actually points at) and uses that to look up which function to call."
请注意,编译器在每种情况下生成的代码都不同,行为也会不同。在第一种情况下,编译器确切地知道要调用哪个函数。在第二种情况下,编译器不知道要调用什么函数,必须生成一些额外的代码才能运行。但是,另一方面,如果您没有带有虚拟 name
函数的 Shape
类型,您可以使 "decode the bytes of the network" 代码片段与您的第一个函数一起使用,因为编译器必须提前知道它将通过网络看到什么类型。
有人建议将此问题标记为 a duplicate of this older question on templates and inheritance,即使它在表面上不是同一个问题。一旦您知道此上下文中的 auto
关键字表示 "this is really a template function," 您可以查看其他提出的问题以获得 静态多态性 之间差异的其他示例(使用模板)和运行时多态性(使用虚函数)。