为什么会这样?
当您在c ++ Ex中创建抽象类时: A类(具有纯虚函数) 之后 B类继承自 A
类如果 A类具有名为 A()的构造函数 假设我创建了一个对象 B类,那么编译器首先初始化基类,即 A类,然后初始化类B < / strong>那么.......?
首先,我们不能在没有Object的情况下访问任何类的构造函数,那么如果我们不能创建抽象类的对象,它是如何初始化抽象类的构造函数的。
答案 0 :(得分:8)
快速回答:构造函数很特殊。
当A的构造函数仍在运行时,正在构造的对象尚未真正属于A类。它仍在构造中。当构造函数完成时,它现在是A。
对于派生的B,它是相同的.A的构造函数首先运行。现在它是A.然后B的构造函数开始运行。在此期间,对象仍然是A。只有当B的构造函数完成时,它才会成为B。
您可以通过尝试从构造函数调用纯虚函数来验证这一点。如果函数在A中定义,并且B的构造函数调用它,则会出现运行时错误,而不是运行B的覆盖,因为该对象尚未出现类型B.
由于纯虚函数,编译器不允许生成构造A的代码。但它会生成代码来构造A作为构建B的过程的一部分。这里没有任何魔法。你不能构造A的规则是由语言规则强加的,而不是物理规则。语言在构建B对象的特殊情况下提升了规则。
答案 1 :(得分: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类布局可能是这样的:
+---------+ +---------+ | vftable | --> | ~A() | --> address of A::~A() +---------+ +---------+ | i | | foo() | --> NULL, pure virtual +---------+ +---------+
B类布局可能是这样的:
+---------+ +---------+ | vftable | --> | ~B() | --> address of B::~B() +---------+ +---------+ | i | | foo() | --> address of B::foo() +---------+ +---------+ | j | +---------+
答案 2 :(得分: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() {..}
};
答案 3 :(得分: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类的所有信息。
答案 4 :(得分:0)
仅仅因为你无法直接实例化类A
并不意味着实例化类A
是不可能的。您不能实例化A
因为编译器知道A
是抽象的并且拒绝您尝试直接实例化A
的任何代码。它禁止这样的代码:
A a;
new A();
使类抽象的原因是它具有纯虚方法。但是,没有任何东西可以阻止这样的类被实例化。 C ++标准简单地说它是不允许的。编译器完全能够生成实例化抽象类的指令。它所要做的就是保留适量的内存,然后调用构造函数,就像对非抽象类一样。
当您实例化B
时,该类的所有内存都会立即被分配。由于所有字节都在那里,因此在那里基本上有一个A
实例,准备由构造函数初始化。 (但请注意,在A
构造函数完成运行之后 A
构造函数运行时,内存不会被正式视为A
类型的对象。)B
构造函数运行,然后运行{{1}}构造函数。