这是一个C ++(11)问题。
我有一个对象Obj myObj
封装了f
类型的对象MyType
。
根据运行时上下文,对象f
的行为应该不同。
实现这一点的一种自然方式是让类Obj
封装一个指向抽象基类MyType
的指针,这将根据上下文指向{的不同(公共)子项。 {1}},例如MyType
,MyType1
等
但是,我并不十分热衷于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
),它可以解决某种物理Obj
(Equation
),其确切的定义取决于问题的维度,1D空间中的等式与2D或3D中的等式不同。 MyType
的代码在Solver
的维度上完全独立,也不必处理指针。 Equation
会隐藏其外部世界的一维,二维或三维实现。
(最初是code review上的一个帖子,因为抽象而暂停)
答案 0 :(得分:-1)
这个提议的课堂设计似乎有一个明显的问题。多态类型由std::unique_ptr
引用:
std::unique_ptr<MyTypeImpl> implPtr_;
Obj
的默认复制构造函数,赋值运算符将最终将保持的指针传递给新对象,使原始对象中的std::unique_ptr
盯着{{1} }。不好。
至少应该是nullptr
或std::shared_ptr
的复制构造函数,赋值运算符需要实例化一个新的Obj
。请注意,通过简单的implPtr_
修复,复制构造函数和赋值运算符的结果是多个std::shared_ptr
实例引用Obj
的相同实例,这可能是也可能不是问题
更简单的类设计只是让MyTypeImpl
和MyTypeImpl1
成为MyTypeImpl2
的子类,实现所需的多态行为。
答案 1 :(得分:-2)
我刚刚重构了你的代码。
vendor