【问题标题】:Interesting C++ Abstract Function有趣的 C++ 抽象函数
【发布时间】:2010-09-26 18:35:53
【问题描述】:

为什么会这样?

当你在 C++ 中创建抽象类时,例如:Class A(具有纯虚函数) 之后 class B 继承自 class A

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

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

【问题讨论】:

    标签: c++ internals


    【解决方案1】:

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

    A a;
    new A();
    

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

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

    【讨论】:

      【解决方案2】:
       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 类的所有信息。

      【讨论】:

        【解决方案3】:

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

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

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

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

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

        【讨论】:

        • 在尝试从构造函数调用虚方法并看到结果后,永远记住不要在构造函数中调用虚方法:)
        • 然后忘记 C++/CLI 中不适用的规则!
        【解决方案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 | +----------+

        【讨论】:

        • 感谢您的回答,但我想知道它是如何创建抽象类的内部对象的??????
        • 对一个简单问题的详细回答太荒谬了。
        • 也许,我先做了一个简单的回答,但这并没有回答达山的问题。
        【解决方案5】:
        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() {..}
        };
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-06-10
          • 2013-01-15
          • 2010-12-12
          • 2023-03-04
          • 2014-10-07
          • 2011-10-10
          • 2014-06-27
          相关资源
          最近更新 更多