简体   繁体   English

如何通过重用基类构造函数来实现派生类构造函数?

[英]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协程器时,您还调用了ProgrammerTester的重载协程器,您调用的版本是那些将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.尽管idname参数不会被ProgrammerTester构造函数使用(因为传递给它们的Employee基 class 是虚拟的,并且将由最派生的 object 和ProjectManager构造),我们仍然传递这些值。 There are a couple of reasons for that.有几个原因。

  1. Because we already have these string objects, and the constructors take their parameters as references, we avoid the overhead of constructing temporary string objects that will be unused.因为我们已经有了这些string对象,并且构造函数将它们的参数作为引用,所以我们避免了构造将不使用的临时字符串对象的开销。
  2. The code does not rely on the assumption that the id and name paramaters are unused.该代码不依赖于未使用idname参数的假设。 It is possible that a future change to the constructors will make use of one or both parameters.将来对构造函数的更改可能会使用一个或两个参数。 By passing in the expected values that can avoid future bugs.通过传入可以避免未来错误的预期值。

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM