6

我有一个关于风格的问题。我有一个类(在我的例子中是一个选项),它取决于外生对象的值(利率)。我的目标是为外生对象 (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; }
}
4

2 回答 2

5

你的担心是有道理的。由于您将客户端传入的对象存储到引用中,因此您相信该客户端会在您需要时保持对象的活动状态。这很容易导致问题。当然,如果您使用原始指针来动态分配对象,情况也是如此。如果客户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被销毁时,因为它是成员)。

或者,如果您采取 astd::shared_ptr那么一旦客户和您std::shared_ptr的 s 都被销毁,该对象将被销毁。

于 2013-03-05T01:00:20.200 回答
3

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

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

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

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

class ExogenousVariationA : public Exogenous
{
public:
    double interfaceMethod() const { return resultA; }
}
于 2013-03-05T02:07:55.137 回答