如何通过重用 base-class 构造函数来实现 derived-class 构造函数?

How can I implement derived-class constructors by reusing base-class constructors?

让我们看看下面的class:

ProjectManager.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();
}

输出

C:\Users\pc\source\repos\input_cpp_files\cmake-build-debug\input_cpp_files.exe
(id, name, ,)

Process finished with exit code 0

正如我们所见,程序没有给出正确的输出。

预期输出为:

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

如何在 ProjectManager 中实现构造函数以便它们提供正确的输出?




附加源代码

Employee.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

#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

#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

您的 4 参数 ProjectManager 构造函数调用 1 参数 Programmer 构造函数,它不设置 programming_language_ 成员。 Tester 构造函数也是如此。

所以你的两个 class 的成员变量都没有得到除默认初始化为空字符串之外的任何东西。

解决方案是在正确的参数中传递正确的值,并以正确的顺序构造基础 classes。

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)
        {}
        // ...
    };

即使 idname 参数不会被 ProgrammerTester 构造函数使用(因为 Employee 基 class 它们被传递给是虚拟的,将由最派生的对象构造,ProjectManager),我们仍然传递这些值。有几个原因。

  1. 因为我们已经有了这些 string 个对象,并且构造函数将它们的参数作为引用,所以我们避免了构造将不被使用的临时字符串对象的开销。
  2. 代码不依赖于 idname 参数未使用的假设。将来对构造函数的更改可能会使用一个或两个参数。通过传递可以避免未来错误的预期值。

问题是,当您调用 ProjectManger 构造函数时,您还调用了 ProgrammerTester 的重载构造函数,您调用的版本是那些以参数一为参数的版本std::string,那些构造函数改变了Employee::id_的值,实际上你从来没有改变其他值。 要解决问题,您必须更改

ProjectManager(std::string& id, std::string& name, std::string& programming_language, std::string& tool) : 
Employee(id, name), 
Programmer(programming_language), 
Tester(tool) 
{}

ProjectManager(std::string& id, std::string& name, std::string& programming_language, std::string& tool) : 
Employee(id, name), 
Programmer("","",programming_language), 
Tester("","",tool) 
{}