Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/124.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/silverlight/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 有趣的C++;抽象函数_C++_Internals - Fatal编程技术网

C++ 有趣的C++;抽象函数

C++ 有趣的C++;抽象函数,c++,internals,C++,Internals,为什么会发生这种情况 当C++在C++中创建抽象类:类A(具有纯虚函数) 之后,B类继承自A类 如果类A的构造函数调用了A() 假设我创建了类B的对象,那么编译器首先初始化基类,即类A,然后初始化类B,然后 首先,如果没有对象,我们不能访问任何类的构造函数,那么如果我们不能创建抽象类的对象,那么如何初始化抽象类的构造函数呢。为了构造类B,它必须实现类A的所有纯虚拟成员函数 class A { public: A() {} virtual ~A() {} virtual v

为什么会发生这种情况

当C++在C++中创建抽象类:<强>类A<强>(具有纯虚函数) 之后,B类继承自A类

如果类A的构造函数调用了A() 假设我创建了类B对象,那么编译器首先初始化基类,即类A,然后初始化类B,然后


首先,如果没有对象,我们不能访问任何类的构造函数,那么如果我们不能创建抽象类的对象,那么如何初始化抽象类的构造函数呢。为了构造
类B
,它必须实现
类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;
};
类布局可以是这样的:

+---------+ +---------+ | vftable | --> | ~A() | --> address of A::~A() +---------+ +---------+ | i | | foo() | --> NULL, pure virtual +---------+ +---------+ +---------+ +---------+ | vftable | --> | ~B() | --> address of B::~B() +---------+ +---------+ | i | | foo() | --> address of B::foo() +---------+ +---------+ | j | +---------+
A a;
new A();
+---------+ +---------+ |vftable |-->| ~A()|-->A的地址::~A() +---------+ +---------+ |i | | foo()|-->NULL,纯虚拟 +---------+ +---------+ B类布局可以是这样的:

+---------+ +---------+ | vftable | --> | ~A() | --> address of A::~A() +---------+ +---------+ | i | | foo() | --> NULL, pure virtual +---------+ +---------+ +---------+ +---------+ | vftable | --> | ~B() | --> address of B::~B() +---------+ +---------+ | i | | foo() | --> address of B::foo() +---------+ +---------+ | j | +---------+
A a;
new A();
+---------+ +---------+ |vftable |-->| ~B()|-->B的地址::~B() +---------+ +---------+ |i | | foo()|-->B::foo()的地址 +---------+ +---------+ |j| +---------+
快速回答:构造函数是特殊的

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

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

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

由于纯虚函数,编译器将不允许您生成将构造A的代码。但它将生成代码来构造A,作为构造A B过程的一部分。这其中没有魔法。不能构造A的规则是由语言规则而不是物理规则强加的。该语言在构造B的对象的特殊情况下解除了该规则。

struct A{
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() {..}
};
A(int x){..} 虚空do()=0; }; 结构B:公共A{ B():A(13){}// 事实上,你的想法是错误的:

创建类B的对象时,将调用类B的构造函数。
如果未指定B构造函数如何调用构造函数,则编译器将自动在初始值设定项列表中的第一个操作中插入对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 .

<>你把上面提到的东西看成是一个B和B不同的东西。B类的对象也是类A的对象。它是一个整体有效的对象。整个对象是B类,但这包含(作为同一对象的一部分)。所有来自类A的信息。

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

+---------+ +---------+ | vftable | --> | ~A() | --> address of A::~A() +---------+ +---------+ | i | | foo() | --> NULL, pure virtual +---------+ +---------+ +---------+ +---------+ | vftable | --> | ~B() | --> address of B::~B() +---------+ +---------+ | i | | foo() | --> address of B::foo() +---------+ +---------+ | j | +---------+
A a;
new A();

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


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

谢谢你的回答,但我想知道它是如何创建抽象类的内部对象的?对于一个简单的问题,答案过于复杂。也许,我先做了一个简单的回答,但那没有回答Darshan的问题。在尝试调用从构造函数中调用虚拟方法并查看结果时,请始终记住不要在构造函数中调用虚拟方法:),然后忘记C++/CLI中不适用的规则!