3

为什么会这样?

当您在c ++中创建抽象类时:从类A继承类B之后的类A(具有纯虚函数)

如果A 类 有一个名为A()的构造函数, 假设我创建了B 类的一个对象 ,那么编译器首先初始化基类,即A 类,然后初始化B 类然后.......?

首先是我们不能访问没有 Object 的任何类的构造函数,那么如果我们不能创建抽象类的对象,它是如何初始化抽象类的构造函数的。

4

5 回答 5

8

快速回答:构造函数是特殊的。

当 A 的构造函数仍在运行时,则正在构造的对象还不是真正的 A 类型。它仍在构造中。当构造函数完成时,它现在是一个 A。

派生的 B 也是如此。 A 的构造函数首先运行。现在它是一个 A。然后 B 的构造函数开始运行。在此期间,对象仍然是真正的 A。只有当 B 的构造函数完成时,它才会成为 B。

您可以通过尝试从构造函数调用纯虚函数来验证这一点。如果函数在 A 中定义,并且 B 的构造函数调用了它,则会出现运行时错误,而不是运行 B 的覆盖,因为对象还不是 B 类型。

由于纯虚函数,编译器将不允许您生成将构造 A 的代码。但它会生成代码来构造 A 作为构造 B 的过程的一部分。这并不涉及任何魔法。不能构造 A 的规则是语言规则而不是物理学强加的。在构造 B 的对象的特殊情况下,该语言提升了该规则。

于 2008-12-13T09:53:25.470 回答
4

class A是抽象的,但class B不是。为了构造class B,它必须实现所有的纯虚成员函数class A

class A
{
public:
    A() {}
    virtual ~A() {}
    virtual void foo() = 0; // pure virtual
    int i;
};


class B : public A
{
public:
    B() {}
    virtual ~B() {}
    virtual void foo() {}
    int j;
};

A 类布局可能是这样的:

+---------+ +---------+
| 可变表 | --> | 〜A()| --> A::~A() 的地址
+---------+ +---------+
| 我 | | 富()| --> NULL,纯虚拟
+---------+ +---------+

B 类布局可能是这样的:

+---------+ +---------+
| 可变表 | --> | 〜B()| --> B::~B() 的地址
+---------+ +---------+
| 我 | | 富()| --> B::foo() 的地址
+---------+ +---------+
| j |
+----------+
于 2008-12-13T09:52:15.533 回答
1
struct A {
  A(int x) {..}
  virtual void do() = 0;
};

struct B : public A {
   B() : A(13) {}      // <--- there you see how we give params to A c'tor
   virtual void do() {..}
};
于 2008-12-13T10:17:04.253 回答
0
 And if class A has constructor called A() suppose i created an
 Object of class B then the compiler initializes the base class
 first i.e.class A and then initialize the class B
 Then.......?

实际上你有错误的方法:

当您创建 B 类的对象时,将调用 B 的构造函数。
如果您没有指定 B 构造函数如何调用 A 构造函数,那么编译器将自动插入对 A 的默认构造函数的调用作为初始值设定项列表中的第一个操作。

如果您不想使用默认构造函数,则必须显式调用适当的 A 构造函数作为初始值设定项列表中的第一个元素。

当A的建设完成后,B的建设将继续。

First thing is we can not access a constructor of any class without an Object
then how it is initialize the constructor of abstract class if we can not create
an object of abstract class .

您说上面的话,就好像您考虑 A 和 B 不同的事情一样。B 类的对象也是 A 类的对象。有效的是作为一个整体的对象。整个对象属于 B 类,但这包含(作为同一对象的一部分)来自 A 类的所有信息。

于 2008-12-13T17:18:14.163 回答
0

不能直接实例化 classA并不意味着不能实例化 class A。您不允许实例化A,因为编译器知道这A是抽象的,并拒绝您编写的任何试图直接实例化的代码A。它禁止这样的代码:

A a;
new A();

使类抽象的原因在于它具有纯虚方法。但是,没有什么本质上阻止这样一个类被实例化。C++ 标准只是简单地说这是不允许的。编译器完全能够生成指令来实例化一个抽象类。它所要做的就是保留适量的内存,然后调用构造函数,就像它对非抽象类一样。

当您实例化时B,该类的所有内存都会立即分配。由于所有字节都在那里,因此那里基本上有一个A实例,准备好由构造函数初始化。(但请注意,在构造函数完成运行A之前,内存不会被正式视为类型对象。)构造函数运行,然后构造函数运行。AAB

于 2008-12-13T17:46:29.007 回答