虚拟方法在 C++0x 中不能"delete"吗?
Are virtual method not "delete"able in C++0x?
当我们尝试使用delete
和virtual
方法时,错误消息似乎与场景有点错误。
prog.cpp:4:16: error: deleted function 'virtual void Test::foo()'
prog.cpp:8:2: error: used here
代码
struct Test : public Base
{
Test() {}
virtual void foo () = delete; // error
};
virtual
方法不能delete
是因为同样的原因吗?为什么它们不能在C++03中保持未实现?有没有办法提到Test
故意不执行virtual foo()
?
术语use在标准中有一个具体的定义,特别是对于虚拟函数,odr的定义为:
§3.2/2(C++0x FDIS)[…]如果虚拟成员函数不是纯的,则使用它。[…]
其中odr使用是即将发布的标准中的一个新术语,指的是之前的标准中明确使用的:
§3.2/2(当前标准)[…]如果虚拟成员函数不是纯的,则使用该函数。[…]
我的看法是,错误消息使用中使用的术语来指代在这种特定情况下使用的odr,是的,这是一个违规的原因与您不能让非纯虚拟成员函数未实现的原因完全相同。
所有非纯虚拟函数都必须实现,无论您是否使用它们:
struct Test
{
Test() {}
virtual void foo();
};
int main() {
Test* t = new Test;
// ^ it seems to have to be dynamic allocation to coerce the error out
}
/* Output:
/home/Y3oGMf/ccOLuYWf.o: In function `main':
prog.cpp:(.text+0x17): undefined reference to `vtable for Test'
collect2: ld returned 1 exit status
*/
我想您看到了一条有点奇怪的错误消息,关于出于类似的原因使用已删除函数。这只是因为事情内部是如何运作的。一个更合理的错误消息可能在您尝试delete
virtual
函数成员的行上,说"这行不通。它会引起问题,因为这个实现必须存在。"
无论如何,delete
作为一个接口函数是没有意义的。继承增加了功能;它不会带走它。请注意,使成员函数为纯虚拟函数会禁止实例化整个类:派生类必须重新实现该功能,以免丢失该功能。
我的理解是delete关键字用于删除编译器生成的默认实现。对于虚拟方法,编译器并没有生成默认的实现。
允许删除虚拟函数,但不允许覆盖它们。
§10.3(11)规定:
类中声明的虚拟函数应定义为,或在该类中声明为纯函数(10.4),或两者兼有;但不需要诊断(3.2)。
§8.4.1规定定义了一个被删除的函数。
§10.3(16)规定:
定义已删除的函数(8.4)不得覆盖定义未删除的函数。同样,没有删除定义的函数不应覆盖具有删除定义的功能。
最后一条规则的目的是确保可以在编译时诊断对已删除函数的调用。
因此,以下代码格式错误:
struct Base {
virtual void foo();
};
struct Derived : public Base {
virtual void foo() = delete;
};
但下面的代码格式很好:
struct Base {
virtual void foo() = delete;
};
struct Derived : public Base {
virtual void foo() = delete;
};
演示
OP有一个编译器错误或QoI问题(很难说是哪一个,因为他没有发布整个代码),这个问题已经修复。
如果派生类无法实现,那么您可能不应该从一个需要某些东西的类派生。也许您一开始就不需要从该类派生。
这就像在说"我正在造一辆更好的车。这是一辆没有轮子的车。"你确定这是一部车吗?
还是你问这个只是出于好奇?
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 为什么我的for循环不能正确获取argv
- 不能在初始值设定项列表中将非常量表达式从类型 'int' 缩小到'unsigned long long'
- 为什么我不能在 FOR LOOP 中使用 i/10,C++?
- 为什么我不能在不创建字符串变量的情况下使用函数的字符串输出
- 为什么模板类中的对象不能返回值
- 为什么我不能在一个类的不同行中声明和定义成员变量?
- 为什么我不能在 C++ 中的特定函数重载中调用同一函数的任何其他重载?
- ld:bind_at_load和-bitcode_bundle(Xcode设置ENABLE_bitcode=YES)不能
- 数组长度,为什么从命令行获取时不能使用它?
- Windows/Cygwin - 不能使用 pybind11 - 犯错误
- 为什么我不能使用 EGL 创建无头 OpenGl 上下文?
- 递归模板化函数不能分配给具有常量限定类型"const tt &"的变量"state"
- 为什么运行时环境不能决定应用 delete 或 delete[] 而不是程序员?
- 为什么我不能用'= delete;'声明一个纯虚函数?
- 为什么我不能将元素重新分配给使用 delete [] 解除分配的数组?
- 为什么不能使用数组delete括号之间的值?
- 替换函数'operator new'不能声明'inline' [-werror,-winline-new-delete]
- 虚拟方法在 C++0x 中不能"delete"吗?