C ++ 11虚拟拷贝构造函数

时间:2013-05-28 13:51:01

标签: c++ design-patterns c++11 copy-constructor

我正在阅读Mark Joshi撰写的C ++设计模式和衍生品定价,并在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);
}

在C ++ 11中,回归新事物可能是不合适的。那么使用C ++ 11处理这个问题的正确方法是什么?

2 个答案:

答案 0 :(得分:12)

  

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

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

X(X const&)

可以签名:

X(X&)

函数clone()只是一个常规(虚拟)函数,它的特殊含义被你 - 用户认可为创建对象克隆的东西,而不是编译器,它不知道是什么clone()确实如此。

  

在C ++ 11中返回新的东西可能是不合适的

的确如此,使用new在C ++ 11中并不是惯用的。事实上,在C ++ 11中你应该(几乎)永远不会使用new,除非你正在进行真正的低级内存管理(你应该避免这种情况,除非你真的必须这样做) - 和在C ++ 14中,您可以删除“几乎”。不幸的是,这可能是需要new的例外情况。

我这样说是因为我相信返回一个unique_ptr听起来像是在这里做的恰当的事情(选项对象必须拥有自己的PayOff对象,并且必须保持活着因为选项对象是活着的),并且C ++ 11中没有std::make_unique()函数(它将在C ++ 14中出现):

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

VanillaOption(或其基类)持有unique_ptr而不是原始指针会使delete PayOff对象返回clone()对象变得不必要}。反过来,没有delete该对象意味着不需要定义用户提供的析构函数,也不需要关注Rule of ThreeRule of Five或其他什么。

只要您可以,请按R. Martinho's Fernandes's advice并转到Rule of Zero

答案 1 :(得分:0)

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

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