在 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
.
我正在尝试学习 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
.