为什么我们不能在C++中为抽象类创建对象?

Moe*_*oeb 7 c++ abstract-class object

我知道在C++中不允许这样做,但为什么呢?如果它被允许怎么办?问题是什么?

GMa*_*ckG 25

从你的另一个问题来看,似乎你不明白班级是如何运作的.类是对数据进行操作的函数集合.

函数本身在类中不包含任何内存.以下课程:

struct dumb_class
{
    void foo(){}
    void bar(){}
    void baz(){}
    // .. for all eternity

    int i;
};
Run Code Online (Sandbox Code Playgroud)

有一个大小int.无论你有多少函数,这个类只会占用操作所需的空间int.当您在此类中调用函数时,编译器将向您传递指向存储类中数据的位置的指针; 这是this指针.

因此,函数位于某个地方的内存中,在程序开始时加载一次,然后等待调用数据进行操作.

虚函数不同.C++标准没有强制要求虚拟函数的行为应该如何进行,而只是该行为应该是什么.通常,实现使用所谓的虚拟表,或简称为vtable.vtable是一个函数指针表,与普通函数一样,只分配一次.

拿这个类,假设我们的实现者使用vtables:

struct base { virtual void foo(void); };
struct derived { virtual void foo(void); };
Run Code Online (Sandbox Code Playgroud)

编译器需要生成两个vtable,一个用于base,一个用于派生.它们看起来像这样:

typedef /* some generic function pointer type */ func_ptr;

func_ptr __baseTable[] = {&base::foo}; 
func_ptr __derivedTable[] = {&derived::foo}; 
Run Code Online (Sandbox Code Playgroud)

它如何使用此表?当您创建上面的类的实例时,编译器会滑入一个隐藏指针,该指针将指向正确的vtable.所以当你说:

derived d;
base* b = &d;
b->foo();
Run Code Online (Sandbox Code Playgroud)

在执行最后一行时,它转到正确的表(__derivedTable在这种情况下),转到正确的索引(在这种情况下为0),并调用该函数.正如你所看到的那样,最终会调用derived::foo,这正是应该发生的事情.

注意,稍后,这与执行相同derived::foo(b),b作为this指针传递.

因此,当存在虚方法时,大小的类将增加一个指针(指向vtable的指针.)多重继承会稍微改变一点,但它大致相同.您可以在C++ - FAQ中获得更多详细信息.

现在,问你的问题.我有:

struct base { virtual void foo(void) = 0; }; // notice the = 0
struct derived { virtual void foo(void); };
Run Code Online (Sandbox Code Playgroud)

base::foo没有实施.这使得base::foo纯粹的抽象功能.所以,如果我打电话给它,如上所述:

derived d;
base* b = &d;
base::foo(b);
Run Code Online (Sandbox Code Playgroud)

我们应该期待什么行为?作为纯粹的虚拟方法,base::foo甚至不存在.上面的代码是未定义的行为,可以做任何事情从无到有,崩溃,中间的任何事情.(或者更糟.)

想想纯粹的抽象函数代表什么.请记住,函数不包含任何数据,它们仅描述如何操作数据.一个纯粹的抽象函数说:"我想调用这个方法并操纵我的数据.你怎么做这取决于你."

因此,当你说"嗯,让我们称之为抽象方法"时,你会回答上述内容:"由我决定?不,你这样做." 它将回复"@#^ @#^".告诉那些说"做这个","没有"的人根本没有意义.

直接回答你的问题:

"为什么我们不能为抽象类创建一个对象?"

希望你现在看到,抽象类只定义具体类应该能够做的功能.抽象类本身只是一个蓝图; 你不住在蓝图中,住在实现蓝图的房子里.


abe*_*thy 5

问题很简单:

  • 调用抽象方法时程序应该怎么做?
  • 更糟糕的是:对于非空函数应该返回什么?

该应用程序可能必须崩溃或引发运行时异常,因此这会导致麻烦.你不能虚拟实现每个抽象函数.