指向派生类的指针是否首先创建Base类?

时间:2015-06-10 23:05:47

标签: c++ pointers inheritance derived-class base-class

我有以下代码

$accountNumber = substr( str_shuffle( md5( time() ) ), 0, $aclenth );
    $accountNumber = 'CYB-' . strtoupper( $accountNumber );

这给了我以下输出:

#include <iostream>
using namespace std;

class B{
    int i;
    public:
    B(){
        cout << "Constructing B\n";
    }
    void print(){
        cout << "Printing from B with size : "<<sizeof(*this)<<endl;
    }
};



class D:public B{
    int i;
    public:
    D(){
        cout << "Constructing D\n";
    }
    void print(){
        cout << "Printing from D with size : "<<sizeof(*this)<<endl;
    }
};


int main(){

    B b;
    b.print();
    D d;
    d.print();

    D* dp;
    dp->print();
}

因此,当您创建指向派生类的指针时,它是不是首先创建基类的实例?我不认为它是真的,因为D类的大小是证明。但它甚至没有调用基类构造函数。谁能解释一下呢?

4 个答案:

答案 0 :(得分:5)

指针不会创建任何内容。指针只是指针 - 包含地址的标量对象。您有责任将指针指向内存中的正确位置。

在您的示例中,指针Dim result As Integer = 0 Dim i, ladderVal, LadderCount, size, valCount As Integer ladderVal = 0 LadderCount = 0 size = A.Length If size > 0 Then For i = 1 To size - 1 If LadderCount = 0 Then LadderCount += 1 ladderVal = A(i) Else If A(i) = ladderVal Then LadderCount += 1 Else LadderCount -= 1 End If End If Next valCount = 0 For i = 0 To size - 1 If A(i) = ladderVal Then valCount += 1 End If Next If valCount <= size / 2 Then result = 0 Else LadderCount = 0 For i = 0 To size - 1 If A(i) = ladderVal Then valCount -= 1 LadderCount += 1 End If If LadderCount > (LadderCount + 1) / 2 And (valCount > (size - (i + 1)) / 2) Then result += 1 End If Next End If End If Return result 未初始化。你从来没有把它指向任何地方,所以它没有任何意义。您尝试调用dp会产生未定义的行为。故事结束。

答案 1 :(得分:3)

现在你的指针根本没有初始化,所以尝试使用它会产生未定义的行为。尝试类似:

D *dp = new D; 
dp->print();
delete dp;

或者做得更好,比如:

std::unique_ptr<D> dp = std::make_unique<D>();
dp->print();

... unique_ptr会在超出范围时自动删除D

但是,请注意,您已将print定义为非虚函数,因此调用的函数将取决于所使用的指针(或引用)的类型, not 它所引用的对象的类型。此外,您还没有定义虚拟dtor。

因此,如果您要做类似的事情:

B *p = std::make_unique<D>();
p->print(); // would invoke B::print, even though the object is a D

...当它超出范围时,它将被错误地销毁,因此你会得到未定义的行为。要更正此问题,您需要将B更改为以下内容:

class B{
    int i;
    public:
    B(){
        cout << "Constructing B\n";
    }
    virtual void print(){
        cout << "Printing from B with size : "<<sizeof(*this)<<endl;
    }
    virtual ~B() = default;
};

执行此操作时,答案为“是” - 当您创建派生对象时,它将首先调用基类的ctor,然后调用派生类的ctor。当派生对象被销毁时,这是相反的:首先调用派生类的dtor,然后当它完成时,将执行基类的dtor。

答案 2 :(得分:3)

它在派生类之前构造基类。你的输出反映了这个。看看这个

//Constructs Base class
Constructing B
//Constructs Derived class
Constructing D
//Prints from derived
Printing from D with size : 8

您的代码在不调用构造函数的情况下两次打印Printing from D with size : 8的原因是您的代码永远不会创建D的第二个实例。

D* d;
^^^^ Declares a pointer to a D, Does not create a D!

当您致电d->print();时,它是未定义的行为,因为d未指向D的实例。最后,您的代码打印在编译时确定的值(sizeof(D)是编译时间值),并且不会触及代码运行的this指针。

请参阅sizeof here的文档。

答案 3 :(得分:2)

您可以使用强大的多态Base指针指定一个Derived对象。这是可能的,因为Derived实现了Base包含的所有内容。因此,隐含Derived基础在其自己的实例化期间实例化Base

class Base
{
public:
    Base()
    {}
}

class Derived : public Base
{
public:
    Derived()
    {}
}

Derived *derived = new Derived();
Base *base = derived;