先左后右,自上而下

丢一道芝麻开门上的题目:

定义一个人员类cpeople,其属性有(保护类型):姓名、性别、年龄;从中派生出学生类cstudent,添加属性:学号、入学时间和入学成绩;从cpeople类再派生出教师类cteacher,添加属性:职务、部门、工作时间;有cstudent类派生研究生类cgraduate,添加属性:研究方向和导师,由cgradute和cteacher共同派生出在职研究生类cgraonwork,分别定义其中的构造函数和输出函数。主函数中定义各种类的对象,并完成测试。

【参考实现】(错误部分已修正)

#include <iostream>
#include <string>
using namespace std;

class cpeople{
protected:
    string name;
    string sex;
    int age;
};

class cstudent:virtual public cpeople{
protected:
    string number;
    int entrance_time;
    int grade;
public:
    cstudent(string name,string sex,int age,string number,int grade){
        this->name=name;
        this->sex=sex;
        this->age=age;
        this->number=number;
        this->grade=grade;
    }
    void show(){
        cout<<"姓名:"<<name<<",性别:"<<sex<<",年龄:"<<age<<",学号:"<<number<<",成绩:"<<grade<<"。"<<endl; } }; class cteacher:virtual public cpeople{ protected: string position; string department; int work_time; public: cteacher(string name,string sex,int age,string position,string department){ this->name=name;
        this->sex=sex;
        this->age=age;
        this->position=position;
        this->department=department;
    }
    void show(){
        cout<<"姓名:"<<name<<",性别:"<<sex<<",年龄:"<<age<<",职务:"<<position<<",部门:"<<department<<"。"<<endl; } }; class cgradute:virtual public cstudent{ protected: string direction; string teacher; public: cgradute(string name,string sex,int age,string direction,string teacher,string number,int entrance_time):cstudent(name,sex,age,number,entrance_time){ this->name=name;
        this->sex=sex;
        this->age=age;
        this->direction=direction;
        this->teacher=teacher;
    }
    void show(){
        cout<<"姓名:"<<name<<",性别:"<<sex<<",年龄:"<<age<<",学号:"<<number<<",成绩:"<<grade<<",方向:"<<direction<<",导师:"<<teacher<<"。"<<endl;
    }

};

class cgraonwork:public cteacher,public cgradute{
public:
    cgraonwork(string name,string sex,int age,string direction,string teacher,string number,int entrance_time,string position,string department):cstudent(name,sex,age,number,entrance_time),cteacher(name,sex,age,position,department),cgradute(name,sex,age,direction,teacher,number,entrance_time){
    }
    void show(){
        cout<<"姓名:"<<name<<",性别:"<<sex<<",年龄:"<<age<<",学号:"<<number<<",成绩:"<<grade<<",方向:"<<direction<<",导师:"<<teacher<<",职务:"<<position<<",部门:"<<department<<"。"<<endl;
    }
};

/* main 函数为Online Judge后置函数,不可更改。*/
int main(int argc, const char * argv[]) {
    cstudent c("小明","男",20,"20160608",90);
    c.show();
    cteacher t("老王","男",55,"系主任","软件工程");
    t.show();
    cgradute g("小红","女",26,"计算机应用","李导","20120607",98);
    g.show();
    cgraonwork w("小东","男",35,"通信工程","梁导","20100606",100,"副主任","通信工程");
    w.show();
    return 0;
}

本地编译运行没有任何问题,然后提交也AC,但是一串长长的红色的Warning惹人心烦:

main.cpp: In constructor `cgraonwork::cgraonwork(std::basic_string<char, 
   std::char_traits<char>, std::allocator<char> >, std::basic_string<char, 
   std::char_traits<char>, std::allocator<char> >, int, std::basic_string<char, 
   std::char_traits<char>, std::allocator<char> >, std::basic_string<char, 
   std::char_traits<char>, std::allocator<char> >, std::basic_string<char, 
   std::char_traits<char>, std::allocator<char> >, int, std::basic_string<char, 
   std::char_traits<char>, std::allocator<char> >, std::basic_string<char, 
   std::char_traits<char>, std::allocator<char> >)':
main.cpp:69: warning: base `cteacher' will be initialized after
main.cpp:69: warning:   base `cstudent'
main.cpp:69: warning:   when initialized here

很明显,Warning几乎全部来自下面的部分,

class cgraonwork:public cteacher,public cgradute{
public:
    cgraonwork(string name,string sex,int age,string direction,string teacher,string number,int entrance_time,string position,string department):cstudent(name,sex,age,number,entrance_time),cteacher(name,sex,age,position,department),cgradute(name,sex,age,direction,teacher,number,entrance_time){

乍一看没什么问题,但是和文溢讨论的时候意识到——

  • 对于非虚基类,构造函数的执行顺序仍是先左后右,自上而下。
  • 对于多个虚基类,构造函数的执行顺序仍然是先左后右,自上而下。

当然了,上面的代码已经经过修正,原始的错误代码已无从查证,但是经过讨论之后我们得出了一致的结论,构造函数的顺序应该与类的声明顺序一致,应该与初始化列表的顺序一致。

分享