C ++:作为成员的抽象类

时间:2013-03-05 00:53:58

标签: c++ coding-style polymorphism abstract-class

我对风格有疑问。我有一个类(在我的情况下是一个选项),它取决于外生对象的价值(利率)。我的目标是为外生对象(Rate)创建一个抽象基类,这样我就可以构建变量,比如SimulatedRate或ConstantRate,它们可以在我的依赖类Option中工作。

但是,我在C ++中发现,因为我显然无法实例化抽象基类,所以我必须存储指针或对基类的引用。我担心的是,当实例化的外部对象超出依赖类之外的范围时,我的依赖类将指向垃圾。

在C ++中是否有合理的方法利用多态来解决这个问题?

我目前的代码:

class Dependent 
{
public:
    Dependent(const Exogenous& exo) : exo_(exo) {}
    double getSomething() const { exo_.interfaceMethod(); }
private:
    Exogenous& exo_;
}

class Exogenous
{
public:
    virtual double interfaceMethod() const=0;
}

class ExogenousVariationA
{
public:
    virtual double interfaceMethod() const { return resultA; }
}

class ExogenousVariationB
{
public:
    virtual double interfaceMethod() const { return resultB; }
}

2 个答案:

答案 0 :(得分:4)

您的担心是有效的。由于您要将客户端传入的对象存储到引用中,因此您信任该客户端以在需要时保持对象处于活动状态。这很容易导致问题。当然,如果您使用原始指针动态分配对象,情况也是如此。如果客户端在完成对象之前对该对象执行delete,则再次出现问题。

解决方案是强制客户端在对象的生命周期内承担某种责任。这样做的方法是要求智能指针。根据您的问题,您可能需要std::unique_ptrstd::shared_ptr。如果您想从客户端获取所有权,请使用前者,如果您想与他们共享所有权,请使用后者。假设您选择std::unique_ptr,然后将Dependent类定义为:

class Dependent 
{
public:
    Dependent(std::unique_ptr<Exogenous> exo) : exo_(std::move(exo)) {}
    double getSomething() const { exo_->interfaceMethod(); }
private:
    std::unique_ptr<Exogenous> exo_;
}

客户端会像这样使用它:

std::unique_ptr<Exogenous> ptr(new ExogenousVariationA());
Dependent dep(std::move(ptr));

现在,当您的客户将std::unique_ptr传递给您时,他们会授予您对该对象的所有权。只有当你的 std::unique_ptr被销毁时才会销毁该对象(这将是你的Dependent被销毁的时候,因为它是一个成员)。

或者,如果您使用std::shared_ptr,则一旦客户端和std::shared_ptr被销毁,该对象将被销毁。

答案 1 :(得分:3)

sftrabbit有一些很好的建议,我要补充一下:

  • 你可以在抽象基类中创建一个virtual clone()方法(它不是虚拟基类 - 完全不同于其他东西);该方法将在派生的利率类中实施,返回指向可由该选项拥有的新独立利率对象的指针;如果对象包含在您使用时更改的数据(例如,来自计算或缓存),则此功能特别有用
  • 你可能不希望这样,但是对于std / boost共享指针,它也可以要求指向共享对象的弱指针......这样你就可以测试对象的“所有者”(赢得了“包括你”已经完成了它并触发了它的破坏

另外,要使用运行时多态性,ExogenousVariationA和〜B类必须实际派生自Exogenous,并且要多态分派的方法必须为virtual。看起来像这样:

class Exogenous
{
public:
    virtual double interfaceMethod() const=0;
}

class ExogenousVariationA : public Exogenous
{
public:
    double interfaceMethod() const { return resultA; }
}