问题描述
我正在研究一个抽象类,稍后将由几个子类派生。然而,几乎所有的功能都是非抽象的——那么为什么我不能分配这个抽象类的对象并使用它,只要我不调用任何纯虚函数呢?毕竟,抽象类的大小在编译时是众所周知的!?
解决方法
抽象类的定义如下:
定义一个不能被实例化但可以用作基类的抽象类型。
来自:https://en.cppreference.com/w/cpp/language/abstract_class
以另一种方式使用它会违背抽象类的使用。
抽象类用于表示一般概念(例如,Shape、Animal),它们可以用作具体类(例如,Circle、Dog)的基类。
不能创建抽象类的对象(除了从它派生的类的基子对象),也不能声明抽象类的非静态数据成员。
另见https://timsong-cpp.github.io/cppwp/n3337/class.abstract
,只要我不调用任何纯虚函数?
除非在微不足道的情况下,否则无法证明这一点。让我们看一个例子。假设这是你的抽象类
class Abby { virtual void fun() const = 0; };
假设您能够创建一个 Abby
对象进行测试。
// First source file
Abby test;
在一个微不足道的情况下,除了将它强制转换为 void
以避免编译器警告有关未使用的变量之外,您实际上什么都不做。在特殊情况下,您可能会将此对象(通过引用)传递给在不同文件中定义的函数,而不是创建对象的文件,可能是以下函数。
// Second source file
void foo(const Abby & o)
{
o.fun();
}
该函数需要一个以 Abby
作为基类的对象,并调用该对象的虚函数。只要禁止直接创建 Abby
对象,此方法就有效。如果放宽这个限制,会发生什么?编译器是否应该将 foo()
标记为可能因您可能在另一个翻译单元中执行的操作而损坏?编译器是否应该忽略这种情况,从而导致运行时错误?
或者,您可能希望对 foo(test)
的调用被标记为使 test
的定义无效?这会很奇怪,一行 (Abby test;
) 的有效性取决于它后面的内容。它还会极大地限制您在测试中可以做的事情,导致编译器问他们为什么要打扰。以这种方式改变规则没有什么好处,为什么要让复杂的语言变得更加复杂?
此外,不需要太多的编程工作就能得到你想要的结果。把纯虚函数注释掉就行了。
class Abby { /* virtual void fun() const = 0; */ };
既然你没有调用它,这应该不会影响你的代码,对吧?如果是这样,您可以改为模拟该功能,如
class Abby { virtual void fun() const {} };
完成测试后还原此更改。
就我个人而言,我可能会从 Abby
派生一个带有虚拟 fun()
成员的类,并使用该具体类而不是抽象类进行测试。但是,OP 在评论中称其为“麻烦事”。
class Concrete : public Abby { void fun() const override {} };