6

我正在阅读 Mark Joshi 的 C++ Design Patterns and Derivatives Pricing 并在 C++11 中实现他的代码。一切都很顺利,直到我在第 4 章讨论虚拟复制构造函数。

PayOffDoubleDigital thePayOff(Low, Up);
VanillaOption theOption(thePayOff, Expiry);

这里的问题是VanillaOption包含对thePayOff. 如果是这种情况并且有人修改thePayOff了 ,则 的行为theOption可能会在不知不觉中被修改。PayOffDoubleDigital他建议的解决方案是在的基类中创建一个虚拟副本构造函数,PayOff以便theOption包含它自己的副本:

virtual PayOff* clone() const = 0;

然后在每个继承的类中定义:

PayOff* PayOffCall::clone() const
{
    return new PayOffCall(*this);
}

Returning new 让我觉得在 C++11 中可能不合适。那么使用 C++11 处理这个问题的正确方法是什么?

4

2 回答 2

12

他建议的解决方案是在 PayOffDoubleDigital 的基类中创建一个虚拟复制构造函数 [...]

首先,clone()它不是复制构造函数。类的复制构造X函数是一个没有返回类型的特殊成员函数,通常具有以下签名:

X(X const&)

并且可能有签名:

X(X&)

函数clone()只是一个常规(虚拟)函数,它的特殊含义被您 - 用户 - 识别为创建对象克隆的东西,但编译器不知道它是做什么clone()的。

Returning new 让我觉得在 C++11 中可能不合适

没错,new在 C++11 中使用不是惯用的。事实上,在 C++11 中,你应该(几乎)永远不要使用new,除非你正在做非常低级的内存管理(除非你真的必须这样做,否则你应该避免这样做) - 而在 C++14 中,你可以删除“几乎”。不幸的是,这可能是需要的特殊情况new

我这样说是因为我相信返回 aunique_ptr听起来像是在这里做的合适的事情(选项对象必须拥有自己的PayOff对象,并且只要选项对象还活着,它就必须保持活动状态),并且没有std::make_unique()功能在 C++11 中(它将在 C++14 中出现):

std::unique_ptr<PayOff> PayOffCall::clone() const
{
    return std::unique_ptr<PayOff>(new PayOffCall(*this));
}

拥有VanillaOption(或其基类)持有 a而不是unique_ptr原始指针将使. 反过来,不需要那个对象意味着不需要定义用户提供的析构函数,也不需要关心规则、五规则等等。deletePayOffclone()delete

只要有可能,就听从R. Martinho 的费尔南德斯的建议,遵循零规则

于 2013-05-28T14:01:37.840 回答
0

通常在处理所有权时,最简洁的解决方案是返回一个智能指针:它既保证异常安全(没有内存泄漏风险),又明确了对象的所有权。

您是否要使用unique_ptrshared_ptr完全取决于您。

于 2013-05-28T14:00:58.897 回答