一 出错误的代码 开发环境: 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成员。可以参考下图。
- 将参数传递给基类构造函数