当前位置 : 主页 > 手机开发 > 其它 >

继承和构造函数语法造成的一个bug

来源:互联网 收集:自由互联 发布时间:2021-06-19
一 出错误的代码 开发环境: visual studio 2017 社区版 #include "pch.h"#include iostream#include string#include listusing namespace std;//公司类 抽象类或接口class Company{public: Company() {} Company(string str) :name(

  • 出错误的代码
    开发环境: visual studio 2017 社区版
#include "pch.h"
#include <iostream>
#include <string>
#include <list>
using namespace std;

//公司类 抽象类或接口
class Company
{
public:
    Company() {}
    Company(string str)
        :name(str) {}
    virtual void Add(Company* c) = 0;  //增加
    virtual void Remove(Company* c) = 0;  //移除
    virtual void Display(int depth) = 0;  //显示
    virtual void LineOfDuty() = 0;  //履行职责  
    inline bool operator==(const Company& company) const
    {
        return this->name == company.name;
    }
protected:
    string name;
};

class ConcreteCompany : public Company
{
public:
    ConcreteCompany(string name) : Company(name)
    {
        children = new list<Company*>;
    }
    void Add(Company* c) override
    {
        children->push_back(c);
    }
    void Remove(Company* c) override  //删除子节点
    {

        for (list<Company*>::iterator it = children->begin(); it != children->end(); ++it)
        {
            if (*(*it) == *c)
            {
                children->erase(it);
                break;
            }
        }
    }
    void Display(int depth) override  //显示
    {
        for (int ix = 0; ix < depth; ++ix)
        {
            cout << "-";
        }
        cout << this->name << endl;
        for (list<Company*>::iterator it = children->begin(); it != children->end(); ++it)
        {
            (*it)->Display(depth + 2);
        }
    }
    virtual void LineOfDuty() override  //履行职责
    {
        for (list<Company*>::iterator it = children->begin(); it != children->end(); ++it)
        {
            (*it)->LineOfDuty();
        }
    }
private:
    list<Company*>* children;
};

//人力资源部 树叶节点
class HRDepartment : public Company
{
public:
    HRDepartment(string str) : Company(name) {}
    void Add(Company* c) override  //增加
    {

    }
    void Remove(Company* c) override  //移除
    {

    }
    void Display(int depth) override  //显示
    {
        for (int ix = 0; ix < depth; ++ix)
        {
            cout << "-";
        }
        cout << name << endl;
    }
    void LineOfDuty() override  //履行职责  
    {
        cout << this->name << " 员工招聘培训管理" << endl;
    }
};

class FinanceDepartment : public Company
{
public:
    
    FinanceDepartment(string str) : Company(name) {}
    void Add(Company* c) override  //增加
    {

    }
    void Remove(Company* c) override  //移除
    {

    }
    void Display(int depth) override  //显示
    {
        for (int ix = 0; ix < depth; ++ix)
        {
            cout << "-";
        }
        cout << name << endl;
    }
    void LineOfDuty() override  //履行职责  
    {
        cout << this->name << " 公司财务收支管理" << endl;
    }
};

int main()
{
    Company* root = new ConcreteCompany("北京总公司");
    root->Add(new HRDepartment("总公司人力资源部"));
    root->Add(new FinanceDepartment("总公司财务部"));

    ConcreteCompany* comp = new ConcreteCompany("上海华东分公司");
    comp->Add(new HRDepartment("华东分公司人力资源部"));
    comp->Add(new FinanceDepartment("华东分公司财务部"));
    root->Add(comp);

    ConcreteCompany* comp1 = new ConcreteCompany("南京办事处");
    comp1->Add(new HRDepartment("南京办事处人力资源部"));
    comp1->Add(new FinanceDepartment("南京办事处财务部"));
    comp->Add(comp1);

    ConcreteCompany* comp2 = new ConcreteCompany("杭州办事处");
    comp2->Add(new HRDepartment("杭州办事处人力资源部"));
    comp2->Add(new FinanceDepartment("杭州办事处财务部"));
    comp->Add(comp2);

    cout << "\n结构图" << endl;
    root->Display(1);

    cout << "\n职责:" << endl;
    root->LineOfDuty();

    return 0;
}

编译上述代码,VS2017提示错误

一开始这个错误让我百思不得其解,因此将同样的代码放到Linux下编译调试。g++提示的错误如下:

  • 错误的解决
    经过排查发现,错误出现在下面这两行代码
HRDepartment(string str) : Company(name) {}
FinanceDepartment(string str) : Company(name) {}

其中HRDepartment类和FinanceDepartment类均是继承自Company类,这两个类的构造函数初始化Company类中的成员name。正确的写法应该是

HRDepartment(string str) : Company(str) {}
FinanceDepartment(string str) : Company(str) {}

三 知识补充

  • 派生类不能直接访问基类的私有成员,而必须通过基类方法进行访问。具体的说,派生类构造函数必须使用基类构造函数
  • 创建派生对象时,程序首先创建基类对象,这意味着基类对象应当在程序进入派生类构造函数之前被创建。C++使用成员初始化列表语法来完成这种工作。
  • 看下面一个例子
class TableTennisPlayer
{
private:
    string firstname;
    string lastname;
    bool hasTable;
public:
    TableTennisPlayer(const string &fn = "none",
        const string &ln = "none", bool ht = false);
};
//基类的构造函数
TableTennisPlayer::TableTennisPlayer(const string & fn, const string & ln, bool ht)
    :firstname(fn),lastname(ln),hasTable(ht)
{

}

class RatedPlayer : public TableTennisPlayer
{
public:
    RatedPlayer(unsigned int r = 0, const string& fn = "none",
        const string& ln = "none", bool ht = false);
private:
    unsigned int rating; //派生类需要一个数据成员存储比分
};
//子类的构造函数
RatedPlayer::RatedPlayer(unsigned int r, const string & fn, const string & ln, bool ht)
    :TableTennisPlayer(fn,ln,ht)
{
    this->rating = r;
}

int main()
{
    return 0;
}

先看RatedPlayer的一个构造函数

//子类的构造函数
RatedPlayer::RatedPlayer(unsigned int r, const string & fn, const string & ln, bool ht)
    :TableTennisPlayer(fn,ln,ht)
{
    this->rating = r;
}

其中TableTennisPlayer(fn,ln,ht)是成员初始化列表,它是可执行的代码,调用TableTennisPlayer构造函数。例如,程序中包含以下声明

RatedPlayer rplayerrl(1140,"Mallory","Duck",true);

则RatedPlayer 构造函数将把实参”Mallory","Duck",true赋给形参fn,ln,ht,然后将这些参数作为实参传递给TableTennisPlayer(父类)的构造函数,后者将创建一个嵌套TableTennisPlayer对象,并将数据“Mallory","Duck",true存储在该对象中。然后,程序进入RatedPlayer(子类)构造函数体,完成RatedPlayer 对象的创建,并将参数r的值赋为rating成员。可以参考下图。

  • 将参数传递给基类构造函数
网友评论