c++中的继承.为什么是错的

Inheritance in c++. Why is it wrong?

本文关键字:为什么 继承 c++      更新时间:2023-10-16
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*

正确的格式是:

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

初始化列表用于初始化基类和您自己的成员。你不需要初始化基的成员,它们会自己初始化。

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

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

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

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

但是,您可以在初始化列表中调用基类的构造函数,如下所示

Adult() : Human("Eric"), passportId("N0123") { } 

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

在执行Adult的成员初始化列表之前,调用并执行基类的默认构造函数。在基类子对象初始化期间,将构造(并初始化)成员name(它是基类的成员)。这意味着,在执行派生类的成员初始化列表时,name已经存在,这就是为什么您的程序是病态的。

你应该做的是:选择合适的基类构造函数,以便正确初始化name。你可以这样做:

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

希望对你有帮助。

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

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)
        { 
        }
};

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

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

第一次初始化时:

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)

你把name和n搞混了吗?

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