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

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

本文关键字:工作 实现 C++ 对象 成员 引用      更新时间:2024-09-29

我正在尝试学习C++中的装饰器模式实现。我已经尝试使用引用和指向装饰对象的指针作为成员(组合(来实现装饰器类。一次对decorator的调用就能正常工作。然而,当我尝试将多个装饰器实例链接在一起时,只有当我将指向装饰对象的指针用作装饰器类成员时,它才有效。对于具有装饰对象引用的实现,它意外失败(请参见下面的输出(。我使用的是启用了C++11的GCC。这是代码。类RedRose是一个使用指向基本接口的指针的装饰器,而类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