[英]How can I implement derived-class constructors by reusing base-class constructors?
Let us look at the following class:让我们看看下面的class:
ProjectManager.hh项目经理.hh
#ifndef INPUT_CPP_FILES_PROJECT_MANAGER_HH
#define INPUT_CPP_FILES_PROJECT_MANAGER_HH
#include <string>
#include "Employee.hh"
#include "Programmer.hh"
#include "Tester.hh"
namespace OrganizationNamespace {
class ProjectManager : public Programmer, public Tester {
public:
ProjectManager():Employee(), Programmer(), Tester()
{}
explicit ProjectManager(const std::string& id):Employee(id), Programmer(), Tester()
{}
ProjectManager(std::string&id, std::string &name):Employee(id, name), Programmer(), Tester()
{}
ProjectManager(std::string &id, std::string &name, std::string &programming_language):Employee(id, name), Programmer(programming_language), Tester()
{}
ProjectManager(std::string &id, std::string &name, std::string &programming_language, std::string &tool):Programmer(programming_language), Tester(tool),Employee(id, name)
{}
ProjectManager(ProjectManager const & pm)
{
this->id_ = pm.id_;
this->name_ = pm.name_;
this->programming_language_ = pm.programming_language_;
this->tool_ = pm.tool_;
}
void print() const {
std::cout << "(" << Employee::id_ << ", " << Employee::name_ << ", " << Programmer::programming_language_ << "," << Tester::tool_ << ")"
<< std::endl;
}
};
}
#endif //INPUT_CPP_FILES_PROJECT_MANAGER_HH
main.cpp主文件
#include "Employee.hh"
#include "Programmer.hh"
#include "ProjectManager.hh"
int main()
{
std::string id = "id";
std::string name = "name";
std::string programming_language = "programming-language";
std::string testing_tool = "testing-tool";
OrganizationNamespace::ProjectManager pm(id, name, programming_language, testing_tool);
pm.print();
}
Output Output
C:\Users\pc\source\repos\input_cpp_files\cmake-build-debug\input_cpp_files.exe
(id, name, ,)
Process finished with exit code 0
As we can see the program is not giving the correct output.正如我们所见,程序没有给出正确的 output。
The expected output is:预期的 output 为:
C:\Users\pc\source\repos\input_cpp_files\cmake-build-debug\input_cpp_files.exe
(id, name, programming-language, testing-tool)
Process finished with exit code 0
How can I implement constructors in ProjectManager
so that they give the correct output?如何在
ProjectManager
中实现构造函数,以便它们给出正确的 output?
Additional Source Code附加源代码
Employee.hh员工.hh
#ifndef INPUT_CPP_FILES_EMPLOYEE_HH
#define INPUT_CPP_FILES_EMPLOYEE_HH
#include <iostream>
#include <string>
namespace OrganizationNamespace {
class Employee {
protected:
std::string id_;
std::string name_;
public:
Employee() : id_ (""), name_("") {}
Employee(const std::string &id) : id_(id), name_("") {}
Employee(const std::string &id, const std::string &name) : id_(id), name_(name) {}
Employee(Employee const & emp)
{
this->id_ = emp.id_;
this->name_ = emp.name_;
}
void print() const
{
std::cout << "(" << id_ << ", " << name_ << ")" << std::endl;
}
};
}
#endif //INPUT_CPP_FILES_EMPLOYEE_HH
Programmer.hh程序员.hh
#ifndef INPUT_CPP_FILES_PROGRAMMER_HH
#define INPUT_CPP_FILES_PROGRAMMER_HH
#include "Employee.hh"
namespace OrganizationNamespace {
class Programmer : public virtual Employee {
protected:
std::string programming_language_;
public:
Programmer() : Employee(), programming_language_("") {}
Programmer(std::string id) : Employee(id) {}
Programmer(std::string id, std::string name) : Employee(id, name) {}
Programmer(std::string id, std::string name, std::string programming_language) : Employee(id, name),
programming_language_(
programming_language) {}
void print() const {
std::cout << "(" << id_ << ", " << name_ << ", " << programming_language_ << ")" << std::endl;
}
};
}
#endif //INPUT_CPP_FILES_PROGRAMMER_HH
Tester.hh测试者.hh
#ifndef INPUT_CPP_FILES_TESTER_HH
#define INPUT_CPP_FILES_TESTER_HH
#include <string>
#include "Employee.hh"
namespace OrganizationNamespace {
class Tester : public virtual Employee {
protected:
std::string tool_;
public:
Tester() : Employee(), tool_("") {}
Tester(std::string id) : Employee(id) {}
Tester(std::string id, std::string name) : Employee(id, name) {}
Tester(std::string id, std::string name, std::string tool) : Employee(id, name), tool_(tool) {}
void print() const {
std::cout << "(" << id_ << ", " << name_ << ", " << tool_ << ")" << std::endl;
}
};
}
#endif //INPUT_CPP_FILES_TESTER_HH
The problem is that when you call the ProjectManger
cosntructor you also call the overloaded cosntructors of Programmer
and Tester
, the versions you are calling are those which take as parameter one std::string
, those constructors change the value of Employee::id_
, actually you never changed other values.问题是,当您调用
ProjectManger
协程器时,您还调用了Programmer
和Tester
的重载协程器,您调用的版本是那些将std::string
作为参数的版本,这些构造函数实际上更改了Employee::id_
的值你从未改变过其他价值观。 For fixing the problem you must change为了解决问题,你必须改变
ProjectManager(std::string& id, std::string& name, std::string& programming_language, std::string& tool) :
Employee(id, name),
Programmer(programming_language),
Tester(tool)
{}
in在
ProjectManager(std::string& id, std::string& name, std::string& programming_language, std::string& tool) :
Employee(id, name),
Programmer("","",programming_language),
Tester("","",tool)
{}
Your 4-parameter ProjectManager
constructor calls the 1-parameter Programmer
constructor, which does not set the programming_language_
member.您的 4 参数
ProjectManager
构造函数调用 1 参数Programmer
构造函数,它不设置programming_language_
成员。 The same for the Tester
constructor. Tester
构造函数也是如此。
So neither of the member variables for your two classes get anything other than default initialized to empty strings.因此,除了默认初始化为空字符串之外,您的两个类的成员变量都没有得到任何东西。
The solution is to pass the proper values in the proper parameters, and construct the base classes in the correct order.解决方案是在适当的参数中传递适当的值,并以正确的顺序构造基类。
namespace OrganizationNamespace {
class ProjectManager : public Programmer, public Tester {
public:
// ...
ProjectManager(std::string &id, std::string &name, std::string &programming_language):
Employee(id, name), Programmer(id, name, programming_language), Tester()
{}
ProjectManager(std::string &id, std::string &name, std::string &programming_language, std::string &tool):
Employee(id, name), Programmer(id, name, programming_language), Tester(id, name, tool)
{}
// ...
};
Even though the id
and name
parameters won't be used by the Programmer
or Tester
constructors (because the Employee
base class they are passed to is virtual and will be constructed by the most derived object, ProjectManager
), we still pass in those values.尽管
id
和name
参数不会被Programmer
或Tester
构造函数使用(因为传递给它们的Employee
基 class 是虚拟的,并且将由最派生的 object 和ProjectManager
构造),我们仍然传递这些值。 There are a couple of reasons for that.有几个原因。
string
objects, and the constructors take their parameters as references, we avoid the overhead of constructing temporary string objects that will be unused.string
对象,并且构造函数将它们的参数作为引用,所以我们避免了构造将不使用的临时字符串对象的开销。id
and name
paramaters are unused.id
和name
参数的假设。 It is possible that a future change to the constructors will make use of one or both parameters.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.