在 C++ 中使用对装饰对象的成员引用未按预期工作的装饰器 class 的实现

Implementation of the decorator class in C++ using a member reference to the decorated object not working as expected

我正在尝试学习 C++ 中的装饰器模式实现。我尝试使用引用和指向装饰对象的指针作为成员(组合)来实现装饰器 class。装饰器的单次调用按预期工作。但是,当我尝试将多个装饰器实例链接在一起时,它仅在我将指向装饰对象的指针用作装饰器 class 成员时才起作用。对于带有修饰对象引用的实现,它意外失败(请参阅下面的输出)。我正在使用启用了 C++11 的 GCC。这是代码。 class RedRose 是一个装饰器,使用指向基接口的指针,而 class BlueRose 使用对基接口的引用。如果我犯了一个天真的错误,我很抱歉,但我错过了什么?

#include <iostream>
#include <string>
#include <sstream>

using namespace std;

class Flower
{
public:
    Flower() {}
    virtual string str() = 0;
};

class Rose : public Flower
{
public:
    Rose() {}
    
    string str() override {
        return "A rose";
    }
};

class RedRose : public Rose
{
private:
  Flower *rose;

public:
  explicit RedRose(Flower *rose) : rose{rose} {}
  
  string str() override
  {
      ostringstream oss;
      oss << rose->str() << " that is red ";
      return oss.str();
  } 
};

class BlueRose : public Rose
{
private:
  Flower &rose;

public:
  explicit BlueRose(Flower &rose) : rose{rose} {}
  
  string str() override
  {
      ostringstream oss;
      oss << rose.str() << " that is blue";
      return oss.str();
  } 
};

int main(int argc, char *argv[])
{
    
    Rose rose; // The decorated object
    
    // Chaining together docorator with pointer implementation
    RedRose red_rose{&rose};
    RedRose red_red_rose{&red_rose};
    RedRose red_red_red_rose{&red_red_rose};
    
    cout << red_rose.str() << endl;
    cout << red_red_rose.str() << endl;
    cout << red_red_red_rose.str() << endl;
    
    Rose rose2;
    
    // Chaining together docorator with reference implementation
    BlueRose blue_rose{rose2};
    BlueRose blue_blue_rose{blue_rose};
    BlueRose blue_blue_blue_rose{blue_blue_rose};
    
    cout << blue_rose.str() << endl;
    cout << blue_blue_rose.str() << endl;
    cout << blue_blue_blue_rose.str() << endl;
    
    getchar();
}

这是输出

A rose that is red 
A rose that is red  that is red 
A rose that is red  that is red  that is red 

A rose that is blue
A rose that is blue
A rose that is blue`

如果删除复制构造函数,您就会看到问题:

class Flower
{
public:
    Flower() {}
    Flower(const Flower&) = delete;
    virtual string str() = 0;
};
error: use of deleted function ‘BlueRose::BlueRose(const BlueRose&)’
     BlueRose blue_blue_rose{blue_rose};

BlueRose有一个构造函数采用Flower&,另一个构造函数采用const BlueRose&,所以复制构造函数是首选。

一种解决方案是生成构造函数:

  template<typename T>
  explicit BlueRose(T &rose) : rose{rose} {}

但实际上,您不应该使用引用,因为如果包装对象的生命周期比装饰器短,它们可能会悬空。试试 std::unique_ptr.