简体   繁体   English

C ++中的继承。 为什么错了?

[英]Inheritance in c++. Why is it wrong?

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

So we have base class Human and derived class Adult . 因此,我们有基类Human和派生类Adult in the code (where is the implementation of constructor) you can see comment lines. 在代码中(构造函数的实现在哪里),您可以看到注释行。

Why is it wrong to use such initialization in this situation? 为什么在这种情况下使用这种初始化是错误的?

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

The correct form is: 正确的形式是:

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

The initialization list is for initializing base classes and your own members. 初始化列表用于初始化基类和您自己的成员。 You don't initialize your bases' members, they do that themselves. 您无需初始化基地的成员,而是由他们自己进行。

Using an initializer list you can only initialize your own member variables. 使用初始化程序列表,您只能初始化自己的成员变量。

You have to use the Human constructor in the initializer list: 您必须在初始化列表中使用Human构造函数:

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

The base class is being constructed before the derived class so you won't be able to instantiate the base class' members in the initialization list. 基类是在派生类之前构造的,因此您将无法在初始化列表中实例化基类的成员。

However, you can call the base class' constructor in the initialization list like this 但是,您可以像这样在初始化列表中调用基类的构造函数

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

Before executing the member-initialization-list of Adult , the base class default-constructor is invoked and executed. 在执行Adult的成员初始化列表之前,将调用并执行基类default-constructor。 During the base class subobject initialization, the member name (which is a member of the base class) is constructed (and initialized). 在基类子对象初始化期间,将构造(并初始化)成员name (它是基类的成员)。 That means, by the time the member initialization list of the derived class is executed, name already exists, which is why your program is ill-formed. 这意味着,在执行派生类的成员初始化列表时, name已经存在,这就是您的程序格式错误的原因。

What you should be doing is : select the appropriate base class constructor so as to initialize name properly. 您应该做的是:选择适当的基类构造函数name正确初始化name Here is how you do it: 这是您的操作方式:

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

Hope that helps. 希望能有所帮助。

Member initialiser lists (that is, the initialisers after : in a constructor) can only initialise base classes and members of the constructor's class. 成员初始化程序列表(即,构造函数中:之后的初始化程序)只能初始化基类和构造函数类的成员。 Initialising members of a base class is the job of the base class's constructor. 初始化基类的成员是基类的构造函数的工作。

This does not work because you try to access a member of an object that has not been constructed yet. 这不起作用,因为您尝试访问尚未构造的对象的成员。 What you can do is 你能做的是

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

That works, because it instructs the compiler to create the base class part of your object with the given values. 那行得通,因为它指示编译器使用给定的值创建对象的基类部分。 Later in the code - as you have done already within the constructor - you can access the protected members. 在代码的后面(如您在构造函数中所做的一样),您可以访问受保护的成员。

Because your derived class Adult contains Human as an object and you have to call its constructor in order to create it. 因为您的派生类Adult包含Human作为对象,所以必须调用其构造函数才能创建它。 When your Adult object dies, the destructors are called in reverse order. 当您的Adult对象死亡时,将以相反的顺序调用析构函数。 First Adult 's destructor then Human 's destructor. 首先是Adult的破坏者,然后是Human的破坏者。

In the first initialisation: 在第一次初始化中:

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

you probably forgot the " around the passportId, and on the second: 您可能忘记了" passportId "周围的" ,”第二个:

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

I think you mixed up n and name , and also, looks like you should rather call the parent constructor like so: 我认为您将nname混合在一起,而且看起来您应该这样调用父构造函数:

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

你把名字和n混在一起了吗?

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 C ++。 用错误的构造函数实例化对象? - C++. Object is instantiated with wrong constructor? C ++。 为什么我不能编译此代码? 使用const_cast删除constness有什么问题? - C++. Why I can't compile this code? What is wrong with removing constness using const_cast? 整数C ++的二维向量。 怎么了? - Two dimensional vector of integer C++. What's wrong? No matching Constructor Error For Initialization in c++。我的构造函数有什么问题? - No matching Constructor Error For Initialization in c++. Whats wrong with my constructor? Ofstream在Dev C ++中不起作用。 知道为什么不吗? - Ofstream is not working in Dev C++. Any idea why not? C ++。 为什么std :: cout &lt;&lt; char + int打印int值? - C++. Why std::cout << char + int prints int value? 内存碎片整理/堆压缩 - 在托管语言中很常见,但在 C++ 中则不然。 为什么? - Memory defragmentation/heap compaction - commonplace in managed languages, but not in C++. Why? “?” 在Visual C ++中被转换为&#39;^&#39;。 为什么会这样,出路是什么? - '??' is getting converted into '^' in Visual C++. Why is it happening and what is the way out? 在c ++中出现目录问题。 - Issue with directories in c++. AutoIt和C ++。 统一 - AutoIt and C++. Unicode
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM