以下代码尝试使用引用实现基本的Decorator设计模式,以引用基本组件类Paragraph
#include <string>
#include <iostream>
using std::cout; using std::endl; using std::string;
// component
class Paragraph{
public:
Paragraph(const string& text = "") : text_(text) {}
virtual string getHTML() const { return text_; }
private:
const string text_;
};
// first decorator
class BoldParagraph : public Paragraph {
public:
BoldParagraph(const Paragraph& wrapped): wrapped_(wrapped) {}
string getHTML() const override {
return "<b>" + wrapped_.getHTML() + "</b>";
}
private:
const Paragraph &wrapped_;
};
// second decorator
class ItalicParagraph : public Paragraph {
public:
ItalicParagraph(const Paragraph& wrapped): wrapped_(wrapped) {}
string getHTML() const override {
return "<i>" + wrapped_.getHTML() + "</i>";
}
private:
const Paragraph &wrapped_;
};
int main(){
Paragraph p("Hello, World!");
BoldParagraph bp(p); cout << bp.getHTML() << endl;
BoldParagraph bbp(bp); cout << bbp.getHTML() << endl;
ItalicParagraph ibp(bp); cout << ibp.getHTML() << endl;
}
运行时会生成
<b>Hello, World!</b>
<b>Hello, World!</b>
<i><b>Hello, World!</b></i>
而不是
<b>Hello, World!</b>
<b><b>Hello, World!</b></b>
<i><b>Hello, World!</b></i>
也就是说,如果第二个包装函数getHML()
用于对象BoldParagraph
的相同子类bbp
,则它似乎被跳过,但如果它用于不同的子类{{1}则不会被跳过对象ItalicParagraph
和BoldParagraph
。使用指针而不是引用的类似代码按预期工作。
为什么会这样?
答案 0 :(得分:1)
正在调用默认的复制构造函数。这将创建传入(bp)的原始对象的副本,而不是bp周围的包装。您可以通过声明自己的复制构造函数来修复,但我不推荐它:
WITH [0,1,5,7,9,11] as list
UNWIND list as x
WITH CASE WHEN x = 0 THEN -1 ELSE (x / 5) * 5 END as results
return results
为了澄清,默认的复制构造函数复制了在object中传递的值,如下所示:
BoldParagraph(const BoldParagraph &wrapped) : wrapped_(wrapped) {}
而且,我越是想到它,我认为我的建议修复越多越不正确。可能/可能会有令人讨厌的副作用。我建议通过让你的构造函数指针来修复。
这里的答案将显示具有不执行副本的复制构造函数的可能副作用: Copy Constructor in C++ is called when object is returned from a function?
使用包装而不是副本的复制构造函数的具体示例:
BoldParagraph(const BoldParagraph &original) : wrapped_(original.wrapped_) {}
输出:
void AFunction(BoldParagraph bp)
{
cout << bp.getHTML() << endl;
}
int main() {
Paragraph p("Hello, World!");
BoldParagraph bp(p); cout << bp.getHTML() << endl;
BoldParagraph bbp(bp); cout << bbp.getHTML() << endl;
AFunction(bbp);
答案 1 :(得分:1)
原因是bbp(bp)
bp
类型BoldParagraph
调用(隐式定义的)复制构造函数BoldParagraph::BoldParagraph(const BoldParagraph &)
然后执行成员明智的复制/赋值,例如wrapper_
被切片,然后是Paragraph &
类型,而不是BoldParagraph &
。要解决这个问题,您必须为BoldParagraph::BoldParagraph(const BoldParagraph &)
提供一个明确的复制构造函数,然后调用您的个人:
BoldParagraph(const BoldParagraph& wrapped) : BoldParagraph((Paragraph&)wrapped) {} ;
答案 2 :(得分:0)
哦,太棒了,非常感谢!这很难被发现。我最后添加了这个
BoldParagraph(const BoldParagraph& wrapped) :
BoldParagraph(static_cast<const Paragraph&>(wrapped)) {}
让代码开心