C++ 作为右值引用传递的对象在尝试应用装饰器模式时导致错误
我试图学习装饰器模式,并将以下代码组合在一起。当我显式地创建对象,然后应用装饰器时,它会起作用(例如,代码中的C++ 作为右值引用传递的对象在尝试应用装饰器模式时导致错误,c++,inheritance,decorator,C++,Inheritance,Decorator,我试图学习装饰器模式,并将以下代码组合在一起。当我显式地创建对象,然后应用装饰器时,它会起作用(例如,代码中的circleOne和circleTwo) 但是,当我隐式创建对象时(circleThree和circleFour) 然后,最后一个对象circleFour覆盖第三个对象circleThree的数据 完整代码如下: #include <iostream> using namespace std; struct Shape { virtual string str()
circleOne
和circleTwo
)
但是,当我隐式创建对象时(circleThree
和circleFour
)
然后,最后一个对象circleFour
覆盖第三个对象circleThree
的数据
完整代码如下:
#include <iostream>
using namespace std;
struct Shape {
virtual string str() const = 0;
};
struct Circle : Shape {
double radius;
explicit Circle(const double radius) :
radius{radius} {}
void resize(const double factor) { radius *= factor; }
string str() const override {
return "A circle of radius " + to_string(radius);
}
};
struct Square : Shape {
double length;
explicit Square(const double length) :
length{length} {}
void resize(const double factor) {
length *= factor;
}
string str() const override {
return "A square of side length " + to_string(length);
}
};
struct ColoredShape : Shape {
const Shape &shape;
string color;
ColoredShape(const Shape &shape, const string &color) :
shape{shape}, color{color} {}
//ColoredShape(Shape &&shape, const string &color) :
// shape{shape}, color{color} {}
string str() const override {
return shape.str() + " has the color " + color;
}
};
struct TransparentShape : Shape {
const Shape &shape;
int transparency;
TransparentShape(const Shape &shape, const int transparency) :
shape(shape), transparency(transparency) {}
//TransparentShape(Shape &&shape, const int transparency) :
// shape(shape), transparency(transparency) {}
string str() const override {
return shape.str() + " has " + to_string(transparency) +
"% transparency";
}
};
int main() {
Circle c1{5.6};
ColoredShape cc1{c1, "green"};
TransparentShape circleOne{cc1, 67};
Circle c2{9.5};
TransparentShape tc2{c2, 25};
ColoredShape circleTwo{tc2, "yellow"};
TransparentShape circleThree{
ColoredShape{
Circle{50.6},
"green"
},
67
};
ColoredShape circleFour{
TransparentShape{
Circle{90.5},
25
},
"yellow"
};
cout << circleOne.str() << endl;
cout << circleTwo.str() << endl;
cout << circleThree.str() << endl;
cout << circleFour.str() << endl;
return 0;
}
A circle of radius 5.600000 has the color green has 67% transparency
A circle of radius 9.500000 has 25% transparency has the color yellow
A circle of radius 90.500000 has 25% transparency has the color green has 67% transparency
A circle of radius 90.500000 has 25% transparency has the color yellow
如您所见,第三个圆的数据被第四个圆替换,透明度装饰器应用了两次。如何解决此问题?首先,您的代码具有未定义的行为,因为您正在将临时对象传递给类的const ref成员。但当临时引用超出范围时,它会被销毁,并且您有一个悬空引用 这是错误的代码
struct ColoredShape : Shape {
const Shape &shape;
string color;
ColoredShape(const Shape &shape, const string &color) : // const ref here !!!
shape{shape}, color{color} {}
//ColoredShape(Shape &&shape, const string &color) :
// shape{shape}, color{color} {}
string str() const override {
return shape.str() + " has the color " + color;
}
};
ColoredShape circleFour{
TransparentShape{ // this is a temporary
Circle{90.5},
25
},
"yellow"
};
所以,你基本上有两个选择
template<class Decorated> class Colored: Shape {
std::string color;
Shape;
public:
Colored(Shape &&shape, std::string color): shape(std::forward<Shape>(shape)), color(std::move(color)) {}
};
template<class Decorated> Colored(Decorated &&, std::string) -> Colored<Decorated>;
greenCircle
的类型推断为Colored
,生成的圆是它的私有成员,如果您传递给它一个已经存在的对象
Circle c{2.0};
Colored redCircle(c, "red");
redCircle
的类型是有色的,因此它的成员只是对c
的引用
template<class Decorated> class Colored: Shape {
std::string color;
Shape;
public:
Colored(Shape &&shape, std::string color): shape(std::forward<Shape>(shape)), color(std::move(color)) {}
};
template<class Decorated> Colored(Decorated &&, std::string) -> Colored<Decorated>;
Colored greenCircle(Circle{1.0}, "green");
Circle c{2.0};
Colored redCircle(c, "red");