当我们尝试使用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()
?
答案 0 :(得分:9)
术语 use 在标准中有一个具体的定义,特别是对于虚函数, odr-used 的定义是:
§3.2/ 2(C ++ 0x FDIS)[...]虚拟成员函数如果不是纯粹的,则会被使用。[...]
其中 odr-used 是即将推出的标准中的一个新术语,指的是前一个标准名为使用:
§3.2/ 2(当前标准)[...]如果虚拟成员函数不纯,则使用虚拟成员函数。[...]
我的看法是,在这种特殊情况下,错误消息使用术语使用来引用 odr-used ,是的,这是违规的原因是完全相同的原因,你不能使非纯虚拟成员函数未实现。
答案 1 :(得分:3)
必须实现所有非纯虚函数whether you use them or not:
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
函数成员的行可能会出现更明智的错误消息,说“这不会起作用。它会导致问题,因为此实现必须< / em>存在。“
无论如何delete
接口函数都没有意义。继承增加了功能;它不会带走它。注意如何使成员函数 pure virtual禁止整个类被实例化:派生类必须重新实现该功能,以免它丢失。
答案 2 :(得分:2)
我的理解是delete关键字用于删除编译器生成的默认实现。对于虚方法,编译器不会生成默认实现。
答案 3 :(得分:1)
允许删除虚拟函数,但不会重载它们。
§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问题(很难分辨哪个,因为他没有发布整个代码),这个问题已被修复。
答案 4 :(得分:0)
如果你的派生类无法实现它,也许你不应该从一个需要某些东西的类派生出来。可能你不需要从那个类派生出来。
这就像是在说“我正在制造一辆更好的汽车。这种汽车有点像车,但没有实现车轮。”你确定它首先是一辆汽车吗?
或者你是出于好奇而问这个?