0
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;
        }
};

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

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

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

9 回答 9

8

正确的形式是:

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

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

于 2013-04-18T12:05:45.990 回答
3

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

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

Adult (string n, string id)
    : Human(n), passportId(id)
    {}
于 2013-04-18T12:05:43.670 回答
3

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

但是,您可以像这样在初始化列表中调用基类的构造函数

Adult() : Human("Eric"), passportId("N0123") { } 
于 2013-04-18T12:06:36.503 回答
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)
        { 
        }
};

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

于 2013-04-18T12:12:11.710 回答
1

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

您应该做的是:选择适当的基类构造函数以便name正确初始化。这是您的操作方法:

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

希望有帮助。

于 2013-04-18T12:03:57.513 回答
1

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

于 2013-04-18T12:04:28.463 回答
0

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

于 2013-04-18T12:04:29.063 回答
0

在第一次初始化中:

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

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

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

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

Adult (string n, string id) : Human(n), passportId(id)
于 2013-04-18T12:05:20.240 回答
-2

你把名字和n混淆了吗?

Adult (string n, string id) : name(n), passportId(id) {}
于 2013-04-18T12:03:13.203 回答