在c ++中的继承。为什么这是错的?

时间:2013-04-18 12:00:39

标签: c++ inheritance syntax constructor initialization

class Human 
{
    protected:
        string name;
    public:
        Human () : name ("Jim") {}
        Human (string n) : name (n) {}
};

class Adult : public Human
{
    private:
        string passportId;
    public:
        Adult ()// : name ("Eric"), passportId ("N0123") - *THIS IS ERROR* 
        {
            // this is ok
            name = "Eric";  
            passportId = "N0934956";
        }

        Adult (string n, string id)// : name(n), passportId(id) *THIS IS ERROR*
        { 
            // this is ok
            name = n;
            passportId = id;
        }
};

所以我们有基类和派生类成人。 在代码中(构造函数的实现),你可以看到注释行。

为什么在这种情况下使用这种初始化是错误的?

Adult (string n, string id) : name(n), passportId(id) {} // *THIS IS ERROR*

9 个答案:

答案 0 :(得分:8)

正确的形式是:

Adult(string n, string id) : Human(n), passportId(id) {}

初始化列表用于初始化基类和您自己的成员。你没有初始化你的基地成员,他们自己这样做。

答案 1 :(得分:3)

使用初始化列表,您只能初始化自己的成员变量。

您必须在初始化列表中使用Human构造函数:

Adult (string n, string id)
    : Human(n), passportId(id)
    {}

答案 2 :(得分:3)

在派生类之前构造基类,因此您将无法在初始化列表中实例化基类的成员。

但是,您可以像这样

在初始化列表中调用基类的构造函数
Adult() : Human("Eric"), passportId("N0123") { } 

答案 3 :(得分:1)

在执行Adult的member-initialization-list之前,调用并执行基类default-constructor。在基类子对象初始化期间,构造(并初始化)成员name(它是基类的成员)。这意味着,在执行派生类的成员初始化列表时,name已经存在,这就是您的程序格式错误的原因。

您应该做的是:选择适当的基类构造函数,以便正确初始化name。这是你如何做到的:

Adult (string n, string id) : Human(n), passportid(id) {}

希望有所帮助。

答案 4 :(得分:1)

成员初始化列表(即构造函数中:之后的初始化者)只能初始化基类和构造函数类的成员。初始化基类的成员是基类构造函数的作用。

答案 5 :(得分:1)

这不起作用,因为您尝试访问尚未构造的对象的成员。你能做的是

class Human 
{
    protected:
        string name;
    public:
        Human () : name ("Jim") {}
        Human (string n) : name (n) {}
};

class Adult : public Human
{
    private:
        string passportId;
    public:
        Adult () : Human ("Eric"), passportId ("N0123") 
        {
        }

        Adult (string n, string id) : Human(n), passportId(id)
        { 
        }
};

这是有效的,因为它指示编译器使用给定的值创建对象的基类部分。稍后在代码中 - 正如您在构造函数中已经完成的那样 - 您可以访问受保护的成员。

答案 6 :(得分:0)

因为派生类Adult包含Human作为对象,您必须调用其构造函数才能创建它。当Adult对象死亡时,将以相反的顺序调用析构函数。首先是Adult的析构函数,然后是Human的析构函数。

答案 7 :(得分:0)

在第一次初始化中:

Adult ()// : name ("Eric"), passportId (N0123) - *THIS IS ERROR* 

你可能忘记了passportId周围的"和第二个:

Adult (string n, string id)// : name(name), passportId(id) *THIS IS ERROR*

我认为你混淆了nname,而且看起来你应该像这样调用父构造函数:

Adult (string n, string id) : Human(n), passportId(id)

答案 8 :(得分:-2)

你混淆了名字和n?

Adult (string n, string id) : name(n), passportId(id) {}