这个问题让我想起了一个“老新奇事”(Old New Thing)的帖子:
(链接)。
其中说到:“一位客户询问如何完成某个任务……我并不确定这是个好主意,就像询问如何用牙齿接住棒球或者怎样把芝士汉堡上的所有芝士都去掉。”
我解释了他们方法的几个缺陷……最后总结道:“这个想法充满了危险,我担心我的回答会被视为赞同而不是勉强提供帮助。”
你
可以创建一个只有
virtual
析构函数的抽象基类。但我不确定你为什么要这样做。知道一个对象派生自某个类型(比如
Foo
)应该意味着我知道我可以对这个对象做什么。但在这种情况下,我只知道我可以销毁这个对象,这并没有什么用处。
但你说得对,最显然的方法无法编译:
struct Foo {
virtual ~Foo() = 0;
};
struct Bar : Foo {
~Bar() { }
};
struct Baz : Foo {
~Baz() override { }
};
当我尝试编译这段代码时,出现了链接错误。因为虽然
Bar::~Bar()
和
Baz::~Baz()
已经定义了,但是
Foo::~Foo()
没有定义,而编译器在销毁
Bar
或者
Baz
时会调用
Foo::~Foo()
。
有两种解决方法。第一种是,虚函数不需要是纯虚函数:
struct Foo {
virtual ~Foo() { }
};
struct Bar : Foo {
~Bar() { }
};
struct Baz : Foo {
~Baz() override { }
};
struct Quux : Foo { };
但是你特别要求一个纯虚析构函数。答案确实很奇怪:纯虚函数可以由声明它们为纯虚函数的类定义:
struct Foo {
virtual ~Foo() = 0;
};
Foo::~Foo() { }
struct Bar : Foo {
~Bar() { }
};
struct Baz : Foo {
~Baz() override { }
};
struct Quux : Foo { };
你可以这样做,并不意味着这是一个好主意。在定义函数时将一个函数声明为纯虚函数非常不寻常,因此你可能很少使用到它。
否则,如果派生类的属性和构造函数都相同,而其他方法却完全不同,那么该如何创建抽象类呢?
我认为真正困扰我的是,大多数建议现在都是使用纯虚函数来创建类似Java接口的东西。当你这样做时,你需要声明派生类需要支持的方法,但同时也让这些类可以自由地使用任何有意义的数据成员类型。而你计划只声明数据成员类型必须包含什么,并让这些类型自由地拥有截然不同的数据方法。这似乎是一个坏主意。
virtual
关键字。但我的观点是我不理解你会用这个类/接口做什么。它似乎毫无用处。虽然我不是 C++ 的专家... - Per Johansson