为什么我们不能为C ++中的抽象类创建对象? [英] Why can't we create objects for an abstract class in C++?

查看:158
本文介绍了为什么我们不能为C ++中的抽象类创建对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道C ++不允许这样做,但是为什么呢?

I know it is not allowed in C++, but why? What if it was allowed, what would the problems be?

推荐答案

根据您的其他问题,看来您不理解类的运行方式。类是对数据进行操作的函数的集合。

Judging by your other question, it seems you don't understand how classes operate. Classes are a collection of functions which operate on data.

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

Functions themselves contain no memory in a class. The following class:

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

    int i;
};

大小为 int 。无论您拥有多少函数,此类都仅占用在 int 上进行操作所需要的空间。当您在此类中调用函数时,编译器将向您传递指向该类中数据存储位置的指针。这是 this 指针。

Has a size of int. No matter how many functions you have ever, this class will only take up the space it takes to operate on an int. When you call a function in this class, the compiler will pass you a pointer to the place where the data in the class is stored; this is the this pointer.

因此,该函数位于内存中的某个位置,在您的开始时加载一次程序,然后等待数据进行操作。

So, the function lie in memory somewhere, loaded once at the beginning of your program, and wait to be called with data to operate on.

虚拟功能不同。 C ++标准没有规定虚拟函数的行为应如何进行,仅规定了该行为应如何。通常,实施使用所谓的虚拟表或简称vtable。 vtable是一个函数指针表,与普通函数一样,只分配一次。

Virtual functions are different. The C++ standard does not mandate how the behavior of the virtual functions should go about, only what that behavior should be. Typically, implementations use what's called a virtual table, or vtable for short. A vtable is a table of function pointers, which like normal functions, only get allocated once.

采用此类,并假设我们的实现者使用vtables:

Take this class, and assume our implementor uses vtables:

struct base { virtual void foo(void); };
struct derived { virtual void foo(void); };

编译器将需要创建两个vtable,一个用于基本,一个用于派生。它们将看起来像这样:

The compiler will need to make two vtables, one for base and one for derived. They will look something like this:

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

func_ptr __baseTable[] = {&base::foo}; 
func_ptr __derivedTable[] = {&derived::foo}; 

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

How does it use this table? When you create an instance of a class above, the compiler slips in a hidden pointer, which will point to the correct vtable. So when you say:

derived d;
base* b = &d;
b->foo();

执行最后一行后,它会转到正确的表( __ derivedTable ),转到正确的索引(本例中为0),然后调用该函数。如您所见,最终将调用 derived :: foo ,这正是应该发生的情况。

Upon executing the last line, it goes to the correct table (__derivedTable in this case), goes to the correct index (0 in this case), and calls that function. As you can see, that will end up calling derived::foo, which is exactly what should happen.

请注意,稍后,这与执行 derived :: foo(b)相同,将 b 作为 this 指针。

Note, for later, this is the same as doing derived::foo(b), passing b as the this pointer.

因此,当存在虚拟方法时,大小的类将增加一个指针(指向vtable的指针。)多重继承会对此稍作更改,但基本上是相同的。您可以在 C ++-FAQ 中获得更多详细信息。

So, when virtual methods are present, the class of the size will increase by one pointer (the pointer to the vtable.) Multiple inheritance changes this a bit, but it's mostly the same. You can get more details at C++-FAQ.

现在,向您提问。我有:

Now, to your question. I have:

struct base { virtual void foo(void) = 0; }; // notice the = 0
struct derived { virtual void foo(void); };

base :: foo 没有实现。这使得 base :: foo 成为纯抽象函数。因此,如果我要像上面这样称呼它:

and base::foo has no implementation. This makes base::foo a pure abstract function. So, if I were to call it, like above:

derived d;
base* b = &d;
base::foo(b);

我们应该期望什么行为?作为纯虚拟方法, base :: foo 甚至不存在。上面的代码是未定义的行为,可以执行任何操作,从无到崩溃,介于两者之间。 (或者更糟。)

What behavior should we expect? Being a pure virtual method, base::foo doesn't even exist. The above code is undefined behavior, and could do anything from nothing to crashing, with anything in between. (Or worse.)

考虑一个纯抽象函数代表什么。请记住,函数不接收数据,它们仅描述如何操作数据。一个纯粹的抽象函数说:我想调用此方法并操纵我的数据。如何执行取决于您自己。

Think about what a pure abstract function represents. Remember, functions take no data, they only describe how to manipulate data. A pure abstract function says: "I want to call this method and have my data be manipulated. How you do this is up to you."

所以当您说时, 好吧,我们称之为抽象方法,您在回答上面的问题时说:取决于我?不,您要做。它将回复 @#^ @#^。告诉某人说做这个,不根本没有任何意义。

So when you say, "Well, let's call an abstract method", you're replying to the above with: "Up to me? No, you do it." to which it will reply "@#^@#^". It simply doesn't make sense to tell someone who's saying "do this", "no."

直接回答您的问题:


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

"why we cannot create an object for an abstract class?"

希望您现在看到的是,抽象类仅定义了具体类应具备的功能。抽象类本身只是一个蓝图。您不是生活在蓝图中,而是生活在执行该计划的房屋中。

Hopefully you see now, abstract classes only define the functionality the concrete class should be able to do. The abstract class itself is only a blue-print; you don't live in blue-prints, you live in houses that implement the blue-prints.

这篇关于为什么我们不能为C ++中的抽象类创建对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆