Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.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++ 在这种情况下,谁应该构造对象?_C++_Oop - Fatal编程技术网

C++ 在这种情况下,谁应该构造对象?

C++ 在这种情况下,谁应该构造对象?,c++,oop,C++,Oop,我有以下课程: class PluginLoader { public: PluginLoader(Logger&, PluginFactory&, ConflictResolver&); //Functions. private: //Members and functions }; Logger、PluginFactory和conflictcolver类都是将在应用程序中实现的接口类。我在主程序的顶层创建了一个PluginLoader对象。可

我有以下课程:

class PluginLoader
{
public:
    PluginLoader(Logger&, PluginFactory&, ConflictResolver&);
    //Functions.
private:
    //Members and functions
};

Logger
PluginFactory
conflictcolver
类都是将在应用程序中实现的接口类。我在主程序的顶层创建了一个
PluginLoader
对象。可以在该级别了解
记录器
。但是,
PluginFactory
ConflictResolver
仅在
PluginLoader
类内部使用。所以在顶层创建他们的对象看起来很难看。我该怎么办?如果需要,我可以更改构造函数,尽管我希望保持原样。欢迎提出任何意见。谢谢。

我会让PluginLoader类有指向这些类的指针。我会向前声明类,我不会在任何地方定义类,而是在实现文件中定义,这样其他人就看不见了。这是更好的封装,再加上这样做也减少了编译时间

我不会使用原始指针,但auto_ptr、scoped_ptr或unique_ptr应该可以工作

如果您在构造函数中创建这些对象,或者甚至在以后首次使用(惰性构造)时创建这些对象,那么您不需要向构造函数传递任何内容,您可以删除这些参数

编辑:

从其他评论来看,我可能误解了你的问题。如果您想拥有可自定义的对象,这些对象实现了一个接口,但可以是下面的任何对象,那么您必须在顶层创建它们,并像现在这样传入接口引用/指针


我认为可以使用模板将类类型“传递”到对象中,以便它可以为自己创建这些类。但是,使用模板会使类类型在编译时固定下来,这可能不是您想要的。

我的印象是,您将在构造函数中公开内部内容以进行可能的自定义,但不是典型情况。如果这是正确的,那么一个想法是使这些参数成为可选的,并在没有提供的情况下在内部创建它们

从您的问题和评论来看,您似乎被两个看似冲突的设计原则所迷惑

  • 你应该尽可能多地封装
  • 您不应该在实现中硬连接所需对象的创建
在您的情况下,通过坚持第二个原则,您做得很好(至少从可见的界面上)。这是依赖注入的一个很好的例子。将PluginLoader从创建PluginFactory和ConflictResolver的责任中解放出来是件好事

现在,你认为你违反了第一条原则,这在某种程度上是正确的。因此,回头更仔细地重新审视您的设计问题

PluginLoader到底需要什么?它只需要引用somePluginFactory和ConflictResolver对象。但它不需要自己创造它们。如何解决这个问题

我可以想到两种方法:

  • 具有另一个抽象级别,如在中所做的。在这里 建筑群(或在您的案例中明显复杂的建筑群)和 布线过程将移动到生成器对象。主程序不是 为如何做到这一点而烦恼。它只会触发建筑 过程
  • 另一个工厂可以创建辅助对象,如 PluginFactory和ConflictResolver,只让PluginLoader知道 关于这个新工厂的界面。主程序可以创建 该工厂的一个具体实例,并传递给PluginBuilder
通过使用上述任一方法,您可以消除与原则2的冲突

祝你一切顺利

…类是将在应用程序中实现的所有接口类

PluginFactory
conflictcolver
仅在
PluginLoader
class

这基本上意味着,即使它们仅在内部使用,您也必须公开
PluginFactory
ConflictResolver
的存在,因为您需要客户端实现它们,然后以某种方式(在本例中通过构造函数)将自定义实现传递给
PluginLoader

但是,通过用指针替换引用(最好是智能类型的、唯一的\u ptr将只是作业的工具),可以避免在顶层声明命名对象(在
main
中为静态或自动):


其中
CustomLogger
CustomPluginFactory
customconflictcolver
Logger
的实现,
PluginFactory
ConflictResolver

我认为解决方案是使用一种机制:因此,您可以通过更改一个字符串(可能从配置文件加载)来选择具体的
PluginFactory
ConflictResolver

我开发了一个C++中的依赖注入库。在应用程序中,您可以使用以下代码声明您的PluginLoader类:

REGISTERED_CLASS( PluginLoader, void, void )
{
    ...
private:
    Plug< Logger > logger;
    Plug< PluginFactory > pluginFactory;
    Plug< ConflictResolver > conflictResolver;
};
catalog.Create( "loader", "PluginLoader" );
catalog.Create( "logger", "MyConcreteLogger" );
catalog.Create( "factory", "MyConcretePluginFactory" );
catalog.Create( "resolver", "MyConcreteResolver" );

wallaroo_within( catalog )
{
    use( "logger" ).as( "logger" ).of( "loader" );
    use( "factory" ).as( "pluginFactory" ).of( "loader" );
    use( "resolver" ).as( "conflictResolver" ).of( "loader" );
}

我们为一个应用程序使用了类似的设计,该应用程序使用我们创建的dll。记录器在主应用程序中已知,并在dll中使用。但是,有些对象仅在dll内部使用。我仍然不清楚,如果它们只在内部使用,为什么它们甚至是插件加载程序接口的一部分。其他对象的任何部分是否在外部依赖于这些接口

我想说的是,为什么不为这两个参数使用工厂,PluginFactory,conflictcolver,而根本不将它们作为参数传递

e、 g。 插件加载程序(记录器和)

然后在您的实现中

 PluginLoader(Logger& logger){
    Factory::PluginFactory::GetInstance().useInstance;// example
    Factory::ConflicResolver::GetInstance().useInstance;// exmaple
 }

或者你可以详细说明一下?

我不知道你在问什么,你在做什么。如果您不喜欢依赖注入(看起来这就是您在这里要做的——但是
<catalog>

  <!-- build the objects of your app -->

  <object>
    <name>loader</name>
    <class>PluginLoader</class>
  </object>

  <object>
    <name>logger</name>
    <class>MyConcreteLogger</class>
  </object>

  <object>
    <name>factory</name>
    <class>MyConcretePluginFactory</class>
  </object>

  <object>
    <name>resolver</name>
    <class>MyConcreteResolver</class>
  </object>

  <!-- wiring of the objects: -->

  <relation>
    <source>loader</source>
    <dest>logger</dest>
    <role>logger</role>
  </relation>

  <relation>
    <source>loader</source>
    <dest>factory</dest>
    <role>pluginFactory</role>
  </relation>

  <relation>
    <source>loader</source>
    <dest>resolver</dest>
    <role>conflictResolver</role>
  </relation>

</catalog>
catalog.Create( "loader", "PluginLoader" );
catalog.Create( "logger", "MyConcreteLogger" );
catalog.Create( "factory", "MyConcretePluginFactory" );
catalog.Create( "resolver", "MyConcreteResolver" );

wallaroo_within( catalog )
{
    use( "logger" ).as( "logger" ).of( "loader" );
    use( "factory" ).as( "pluginFactory" ).of( "loader" );
    use( "resolver" ).as( "conflictResolver" ).of( "loader" );
}
 PluginLoader(Logger& logger){
    Factory::PluginFactory::GetInstance().useInstance;// example
    Factory::ConflicResolver::GetInstance().useInstance;// exmaple
 }