Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/137.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用Builder/Fluent模式最小化所需的头文件量_C++_Design Patterns_Pimpl Idiom - Fatal编程技术网

C++ 使用Builder/Fluent模式最小化所需的头文件量

C++ 使用Builder/Fluent模式最小化所需的头文件量,c++,design-patterns,pimpl-idiom,C++,Design Patterns,Pimpl Idiom,我正在尝试用Builder/Fluent风格创建对象,试图扩展课程中提出的一些想法。在我的测试实现中,我立即不喜欢的一个元素是客户端需要包含大量额外的头文件,以便流程正常工作,特别是当我希望通过pImpl习惯用法使用公共/私有头文件来提供库接口时。我不完全确定问题是在于我的实现,还是我只是错过了实现我想要的东西的明显的“最后一步”。 一般要点如下(使用飞行员玩具示例): 首先,客户端代码本身: (注意:为简洁起见,省略了各种样板文件和不相关的代码) 这里发生的是: 在Pilot.h中,

我正在尝试用Builder/Fluent风格创建对象,试图扩展课程中提出的一些想法。在我的测试实现中,我立即不喜欢的一个元素是客户端需要包含大量额外的头文件,以便流程正常工作,特别是当我希望通过pImpl习惯用法使用公共/私有头文件来提供库接口时。我不完全确定问题是在于我的实现,还是我只是错过了实现我想要的东西的明显的“最后一步”。

一般要点如下(使用飞行员玩具示例):

首先,客户端代码本身:
注意:为简洁起见,省略了各种样板文件和不相关的代码)

这里发生的是:

  • Pilot.h中,使用名为
    create()
    的静态成员方法定义
    Pilot
    类,该方法返回在PilotBuilder.h中定义并在Pilot.h中声明的
    PilotBuilder
    类的实例
  • 本质上,
    PilotBuilder
    类是一个方便的构建器,它只用于呈现Pilot的两个不同方面的构建器(
    .works()
    .lifes()
    ),允许您从一个构建器切换到另一个构建器
Pilot.h:

class PilotBuilder;
class Pilot {
private:
    // Professional
    string airline_name_, rank_;    

    // Personal
    string street_address_, city_;

    Pilot(){}
public:
    Pilot(Pilot&& other) noexcept;

    static PilotBuilder create();

    friend class PilotBuilder;
    friend class PilotProfessionalBuilder;
    friend class PilotPersonalBuilder;
};
#include "PilotBuilder.h"

    PilotBuilder Pilot::create() {

        return PilotBuilder();
    }

    // Other definitions etc
Pilot.cpp:

class PilotBuilder;
class Pilot {
private:
    // Professional
    string airline_name_, rank_;    

    // Personal
    string street_address_, city_;

    Pilot(){}
public:
    Pilot(Pilot&& other) noexcept;

    static PilotBuilder create();

    friend class PilotBuilder;
    friend class PilotProfessionalBuilder;
    friend class PilotPersonalBuilder;
};
#include "PilotBuilder.h"

    PilotBuilder Pilot::create() {

        return PilotBuilder();
    }

    // Other definitions etc
PilotBuilder.h

#include "public/includes/path/Pilot.h"

class PilotProfessionalBuilder;
class PilotPersonalBuilder;

class PilotBuilder {    
private:
    Pilot p;
protected:
    Pilot& pilot_;

    explicit PilotBuilder(Pilot& pilot) : pilot_{pilot} {};

public:
    PilotBuilder() : pilot_{p} {}

    operator Pilot() {
        return std::move(pilot_);
    }

    PilotProfessionalBuilder works();
    PilotPersonalBuilder lives();
};
PilotBuilder.cpp

#include "PilotBuilder.h"
#include "PilotProfessionalBuilder.h"
#include "PilotPersonalBuilder.h"

PilotPersonalBuilder PilotBuilder::lives() {
   return PilotPersonalBuilder{pilot_};
}

PilotProfessionalBuilder PilotBuilder::works() {
    return PilotProfessionalBuilder{pilot_};
}
正如您可以想象的那样,
PilotProfessionalBuilder
类和
PilotPersonalBuilder
类使用
PilotBuilder
类提供的引用以流畅的方式实现与特定方面相关的方法,例如(
.atAirline()
),它们的实现与我的查询无关
为了避免向私人成员提供参考这一稍有争议的问题,我的困境是,要利用我目前的模式,客户必须如下所示:

#include "public/includes/path/Pilot.h"
#include "private/includes/path/PilotBuilder.h"
#include "private/includes/path/PilotProfessionalBuilder.h"
#include "private/includes/path/PilotPersonalBuilder.h"

int main() {

    Pilot p = Pilot::create()
            .works().atAirline("Sun Air").withRank("Captain")
            .lives().atAddress("123 Street").inCity("London");
}
我不明白的是:

  • 我如何重新排序或重新实现代码,以便在客户端中简单地使用
    #include“public/includes/path/Pilot.h”
    ,想象一下,比如说,我链接的是一个
    Pilots
    库,实现的其余部分驻留在该库中,并且仍然保持相同的行为
  • 如果有人能在第1点上告诉我,那么有没有办法将
    Pilot
    的私有成员移动到
    唯一的\u ptr pImpl
    中,并且仍然保持静态
    create()
    方法因为以下情况显然是不允许的:
  • :

    最后,我决不是这方面的专家,因此,如果我的任何术语不正确或编码实践确实需要修复,我将很乐意接受人们提供的任何建议。谢谢大家!