【问题标题】:Why did QuantLib introduce the Handle class?QuantLib 为什么要引入 Handle 类?
【发布时间】:2017-03-19 17:44:59
【问题描述】:

我检查了这个slides,但仍然没有得到:

1) what problem does Handle sovled?

2) what is the benefit to add the Handle class?

从它的源代码中,我也无法得到任何线索:

   template <class Type>
    class Handle {
      protected:
        class Link : public Observable, public Observer {
          public:
            explicit Link(const shared_ptr<Type>& h =
                                         shared_ptr<Type>());
            void linkTo(const shared_ptr<Type>&);
            bool empty() const;
            void update() { notifyObservers(); }
          private:
            shared_ptr<Type> h_;
        };
        boost::shared_ptr<Link<Type> > link_;
      public:
        explicit Handle(const shared_ptr<Type>& h =
                                         shared_ptr<Type>());
        const shared_ptr<Type>& operator->() const;
        const shared_ptr<Type>& operator*() const;
        bool empty() const;
        operator boost::shared_ptr<Observable>() const;
    };

    template <class Type>
    class RelinkableHandle : public Handle<Type> {
      public:
        explicit RelinkableHandle(const shared_ptr<Type>& h =
                                         shared_ptr<Type>());
        void linkTo(const boost::shared_ptr<Type>&);
    };

谁能举个更好的例子?

谢谢。

【问题讨论】:

    标签: quantlib


    【解决方案1】:

    简短的回答:Handle 类是指向指针的智能指针。

    它有什么用?以利率指数的一个实例为例,例如Euribor6M。现在,它的构造函数处理了一个收益率期限结构,并据此预测其未来的定价。如果我们改用shared_ptr 会发生什么变化?

    让我们看一个用例。警告:我正在简化事情以避免编写太多代码,但这是我们拥有的合法用例。假设我们用一条平坦的曲线初始化索引:

    shared_ptr<SimpleQuote> r = make_shared<SimpleQuote>(0.01);
    shared_ptr<YieldTermStructure> curve =
        make_shared<FlatForward>(today, r, Actual360());
    
    shared_ptr<InterestRateIndex> index = make_shared<Euribor6M>(curve);
    

    (在实际用例中,curve 将是在一组报价利率上引导的 Euribor 曲线)。 index 的构造函数获取传递的shared_ptr&lt;YieldTermStructure&gt; 的副本并将其复制以存储为数据成员。构建完成后,我们会将指数传递给其他工具(掉期、浮动利率债券等)。

    如果利率发生变化,并且我们仍然持有r 报价,我们的客户端代码可以编写

    r->setValue(0.015);
    

    由于rcurve 是共享指针,这也会改变索引内曲线副本的速率(因为curve 及其在index 内的副本都指向同一个对象)。因此,指数定价和相关工具的价值也会发生变化。

    但是,假设我们要开始使用另一条曲线。在这种情况下,我们可能希望切换到插值曲线而不是平坦曲线:

    vector<Date> dates = ... ;
    vector<Rate> rates = ... ;
    shared_ptr<YieldTermStructure> curve2 =
        make_shared<ZeroCurve>(dates, rates, Actual360());
    

    (在实际情况下,我们可能希望在一组不同的报价上引导曲线或使用另一种方式来模拟费率)。

    我们如何告诉index 它应该开始使用curve2?使用shared_ptr,我们不能。即使我们说:

    curve = curve2;
    

    这将导致curve 指向内插曲线,但index 内部的curve副本 将继续指向旧曲线。这不是shared_ptr 的问题,而是一般的指针。你如何解决它?通过添加另一层间接。如果您使用原始指针,您将开始使用指向指针的指针。在我们的代码中,Handle 做了同样的事情:它“指向”shared_ptr,并且实现了相同句柄的两个副本指向相同的 shared_ptr。这样,如果你写:

    shared_ptr<SimpleQuote> r = make_shared<SimpleQuote>(0.01);
    shared_ptr<YieldTermStructure> curve =
        make_shared<FlatForward>(today, r, Actual360());
    RelinkableHandle<YieldTermStructure> h(curve);
    
    shared_ptr<InterestRateIndex> index = make_shared<Euribor6M>(h);
    

    你可以稍后写:

    h.linkTo(curve2);
    

    您握住的手柄及其在index 中的副本都将指向新曲线。

    至于RelinkableHandleHandle的区别:前者只能调用linkTo。这个想法是你实例化一个RelinkableHandle,将副本传递为Handle,这样你就可以确保除了你之外没有人可以更改它所指向的内容(使用const 是行不通的,因为常量可以被抛弃通过一个简单的副本)。

    【讨论】:

    • 非常感谢您的澄清,Luigi!
    • 感谢您的澄清。对此还有一个问题。 Link 类做了什么,我应该如何考虑传递给链接构造函数的共享指针 h。
    • 链接中的shared_ptr 是当前指向的对象。 Link 类在其之上添加了可观察性,以便您在指向的对象发生更改时收到通知。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-16
    相关资源
    最近更新 更多