Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/backbone.js/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_Inheritance_Polymorphism - Fatal编程技术网

C++ 在添加新的实现时,您将如何重构此多态设计,以使其更加灵活?

C++ 在添加新的实现时,您将如何重构此多态设计,以使其更加灵活?,c++,oop,inheritance,polymorphism,C++,Oop,Inheritance,Polymorphism,我有一个类,它有许多虚拟函数,允许您获取对接口的引用。使用我的API的客户端可以实现我的接口,然后使用它们的实现实现我的顶级接口IMyInterface 然后,我的代码作用于它们的多态IMyInterface实现 下面是一些示例代码(不是真正的代码,但您知道了): 我觉得这个设计看起来很不错,但有一天我想改变其中一个实现,但只有一个。在这种情况下,我必须重写整个类并复制大量代码 实际上有6个Impl对象,所以我必须重写一个类,这个类有5个完全相同的Impl对象,但有一个不同的Impl对象 另一个

我有一个类,它有许多虚拟函数,允许您获取对接口的引用。使用我的API的客户端可以实现我的接口,然后使用它们的实现实现我的顶级接口IMyInterface

然后,我的代码作用于它们的多态IMyInterface实现

下面是一些示例代码(不是真正的代码,但您知道了):

我觉得这个设计看起来很不错,但有一天我想改变其中一个实现,但只有一个。在这种情况下,我必须重写整个类并复制大量代码

实际上有6个Impl对象,所以我必须重写一个类,这个类有5个完全相同的Impl对象,但有一个不同的Impl对象

另一个问题是人们依赖这个API设计,所以我需要保留它的基础知识


是否有一种方法可以修改设计,使其更灵活,同时仍保持此API

我从你的问题中了解到了什么:

如果我理解正确,您使用的是或多或少的类和基本组件的组装,并且您希望能够用最少的代码交换组件

备选方案1:动态装配

为什么不在施工时选择动态装配:

class MyBase : public IMyInterface
{
public:
   Interface1& get1()  { return *pimpl1; }
   Interface2& get2()  { return *pimpl2; }
   //...
   Interfacen& getn()  { return *pimpln; }

protected:
   MyBase (unique_ptr<Interface1> p1, 
             unique_ptr<Interface2> p2, 
             /*...*/ 
             unique_ptr<Interfacen> pn) : // constructor assembles parts
                   pimpl1(move(p1)),pimpl2(move(p2)),/*...*/pimpln(move(pn)) {}
private:
   unique_ptr<Interface1> pimpl1;  // implemented with unique ptr for greater safety
   unique_ptr<Interface2> pimpl2;  
   //...
   unique_ptr<Interfacen> pimpln;
};
class MyBase:public IMyInterface
{
公众:
Interface1&get1(){return*pimpl1;}
Interface2&get2(){return*pimpl2;}
//...
interfaceen&getn(){return*pimplot;}
受保护的:
MyBase(唯一的\u ptr p1,
唯一的_ptrp2,
/*...*/ 
唯一:\u ptr pn)://构造函数组装部件
pimpl1(移动(p1)),pimpl2(移动(p2)),/*…*/PIMPPLN(移动(pn)){}
私人:
unique_ptr pimpl1;//使用unique ptr实现更高的安全性
独特的ptr pimpl2;
//...
唯一的ptr项目;
};
使用这种逻辑,您的派生类将如下所示:

class MyImplementationX : public MyBase {
public: 
   MyImplementationX() : MyBase(make_unique<Impl1>(), make_unique<Impl2>(), /*...*/ make_unique<Impln>()) {}
}; 

class MyImplementationY : public MyBase {
public: 
   MyImplementationX() : MyBase(make_unique<Impl1>(), make_unique<Impl2b>(), /*...*/ make_unique<Impln>()) {}
}; 
类MyImplementationX:公共MyBase{
公众:
MyImplementationX():MyBase(make_unique(),make_unique(),/*…*/make_unique()){}
}; 
类MyImplementationY:公共MyBase{
公众:
MyImplementationX():MyBase(make_unique(),make_unique(),/*…*/make_unique()){}
}; 
备选方案2:编译时程序集

通过使用模板,您可以摆脱运行时程序集、附加分配和智能指针:

template <class I1, class I2, /*...*/ class IN, 
          class M1, class M2, /*...*/ class M3>
class MyBase {
public: 
     I1& get1() { return m1; }
     I2& get2() { return m2; }
     ...
private: 
     M1 m1; 
     M2 m2;
     ...
};
模板
类MyBase{
公众:
I1&get1(){return m1;}
I2&get2(){return m2;}
...
私人:
M1;
M2;
...
};

顺便说一句,有一本关于A. Alexandrescu的“现代C++设计”的优秀书籍,其中作者提倡一个“(有一个用模板实现的策略模式的策略)。p> 也许更适合CodeReview或程序员?例如,为什么您必须“重写整个类并复制大量代码”,从而改变“Impl2”的某些内容?@J。。。代码审查需要工作代码,而不是
等。
“实现”。我不必重写整个类。我只需复制所有代码,并将“Impl2”更改为“Impl8”或其他内容。我只是觉得将来会有问题。每次我想更改单个实现时,都需要复制代码。Impl8是否继承Interface2?等等,为什么那些impl实例是公共的?
template <class I1, class I2, /*...*/ class IN, 
          class M1, class M2, /*...*/ class M3>
class MyBase {
public: 
     I1& get1() { return m1; }
     I2& get2() { return m2; }
     ...
private: 
     M1 m1; 
     M2 m2;
     ...
};