C++ 概念问题:为什么我不能使用部分完成的抽象类?

问题描述

我正在研究一个抽象类,稍后将由几个子类派生。然而,几乎所有的功能都是非抽象的——那么为什么我不能分配这个抽象类的对象并使用它,只要我不调用任何纯虚函数呢?毕竟,抽象类的大小在编译时是众所周知的!?

解决方法

抽象类的定义如下:

定义一个不能被实例化但可以用作基类的抽象类型。

来自: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 {} };