C ++私有多态实现设计

时间:2016-08-28 11:20:50

标签: c++ c++11 polymorphism

这是一个C ++(11)问题。 我有一个对象Obj myObj封装了f类型的对象MyType。 根据运行时上下文,对象f的行为应该不同。

实现这一点的一种自然方式是让类Obj封装一个指向抽象基类MyType的指针,这将根据上下文指向{的不同(公共)子项。 {1}},例如MyTypeMyType1

但是,我并不十分热衷于MyType2“痛苦”Obj多态的后果,即必须处理指针。特别是,如果我将其设为MyType,则意味着std::unique_ptr<MyType>可能无法复制,或者需要为其提供适当的复制构造函数来处理复制MyType资源。

在我看来,Obj多态性不应该是MyType的问题。

我参加了以下课程。本质上,我们的想法是将指针隐藏在Obj私有属性中。另外,我的第二个问题涉及MyType的具体实现可能共享某些代码的事实不应该重复。我把它放在一个私有继承的具体实现的类中。

我很好奇比我更多的专业开发人员会想到它。是否太沉重“只是隐藏指针”?有没有更好的方法呢?

MyTypeImpl

链接到在线编译器:http://cpp.sh/8rhyy

这里的实现非常愚蠢,可以作为一个例子。此设计的应用程序可以是#include <iostream> #include <memory> // a "standard" implementation of MyType class MyTypeImpl { public: virtual double operator()(double a) = 0; virtual int implType() const = 0; virtual void complexStuff() const = 0; }; // some internal stuff common to all implementations class MyTypeImplInternals { protected: MyTypeImplInternals(int value):factor_{value}{} int factor_; void longCommonFunction() const{ std::cout << "I'm doing complex stuff common to all interfaces " << factor_ << "\n" ;} }; // one specific implementation class MyTypeImpl1: public MyTypeImpl, private MyTypeImplInternals { public: MyTypeImpl1(int factor):MyTypeImplInternals{factor}{}; virtual double operator()(double a) override {return factor_*a;} virtual int implType() const override {return 1;} virtual void complexStuff() const override { longCommonFunction(); } }; // a second implementation class MyTypeImpl2: public MyTypeImpl, private MyTypeImplInternals { public: MyTypeImpl2(int factor):MyTypeImplInternals{factor}{}; virtual double operator()(double a) override {return factor_*a;} virtual int implType() const override {return 2;} virtual void complexStuff() const override { longCommonFunction(); } }; class MyTypeImplFactory { public: static std::unique_ptr<MyTypeImpl>createMyTypeImpl(int implementationType) { switch(implementationType) { case 1: return std::unique_ptr<MyTypeImpl> (new MyTypeImpl1(12)); case 2: return std::unique_ptr<MyTypeImpl> (new MyTypeImpl2(22)); default: throw std::runtime_error("implementation does not exist...\n"); return nullptr; } } }; // my type class MyType { public: MyType(int implementationType) { implPtr_ = MyTypeImplFactory::createMyTypeImpl(implementationType); } MyType(MyType const& source) : implPtr_{ MyTypeImplFactory::createMyTypeImpl(source.implType()) } { } double operator()(double a){return (*implPtr_)(a);} int implType() const {return implPtr_->implType();} void complexStuff() const {implPtr_->complexStuff();} private: std::unique_ptr<MyTypeImpl> implPtr_; }; class Obj { private: MyType f; public: Obj(int dim):f{dim}{} Obj(Obj&& sourceToMove) = default; Obj(Obj const& source) = default; void doStuff() {std::cout << "I'm doing stuff() " << f(2) << std::endl; f.complexStuff();} }; int main() { Obj myObj{1}, myObj2{2}; myObj.doStuff(); myObj2.doStuff(); Obj myObj3{std::move(myObj2)}; // myObj2 now dead Obj myObj4{myObj}; myObj3.doStuff(); myObj4.doStuff(); } Solver),它可以解决某种物理ObjEquation),其确切的定义取决于问题的维度,1D空间中的等式与2D或3D中的等式不同。 MyType的代码在Solver的维度上完全独立,也不必处理指针。 Equation会隐藏其外部世界的一维,二维或三维实现。

(最初是code review上的一个帖子,因为抽象而暂停)

2 个答案:

答案 0 :(得分:-1)

这个提议的课堂设计似乎有一个明显的问题。多态类型由std::unique_ptr引用:

std::unique_ptr<MyTypeImpl> implPtr_;

Obj的默认复制构造函数,赋值运算符将最终将保持的指针传递给新对象,使原始对象中的std::unique_ptr盯着{{1} }。不好。

至少应该是nullptrstd::shared_ptr的复制构造函数,赋值运算符需要实例化一个新的Obj。请注意,通过简单的implPtr_修复,复制构造函数和赋值运算符的结果是多个std::shared_ptr实例引用Obj的相同实例,这可能是也可能不是问题

更简单的类设计只是让MyTypeImplMyTypeImpl1成为MyTypeImpl2的子类,实现所需的多态行为。

答案 1 :(得分:-2)

我刚刚重构了你的代码。

vendor