基于策略的设计和最佳实践 - C++
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/872675/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Policy based design and best practices - C++
提问by Navaneeth K N
struct InkPen
{
void Write()
{
this->WriteImplementation();
}
void WriteImplementation()
{
std::cout << "Writing using a inkpen" << std::endl;
}
};
struct BoldPen
{
void Write()
{
std::cout << "Writing using a boldpen" << std::endl;
}
};
template<class PenType>
class Writer : public PenType
{
public:
void StartWriting()
{
PenType::Write();
}
};
int main()
{
Writer<InkPen> writer;
writer.StartWriting();
Writer<BoldPen> writer1;
writer1.StartWriting();
return 0;
}
I wrote the above code as part of learning policy based designs. I have few questions on the above code
我写了上面的代码作为基于学习策略的设计的一部分。我对上面的代码有几个问题
1 - Does this implementation look correct? I mean: does it really look like a policy based design?
1 - 这个实现看起来正确吗?我的意思是:它真的看起来像基于策略的设计吗?
2 - I can now hook any kind of pens to writer. But what will I do when I got a pen with no default constructor (only parameterized constructors)? How will I handle this situation?
2 - 我现在可以将任何类型的笔挂在作家身上。但是当我得到一支没有默认构造函数(只有参数化构造函数)的笔时,我该怎么办?我将如何处理这种情况?
template<class PenType>
class Writer : public PenType
{
public:
void StartWriting()
{
PenType::Write();
}
};
3 - When the above code is used like
3 - 当使用上述代码时
Writer<InkPen> writer;
I guess compiler will replace PenTypewith InkPen. If yes, why I am not able to call just Write()from StartWriting()instead of prefixing base class name (PenType::Write())?
我猜编译器将取代PenType与英克潘。如果是,为什么我不能只从StartWriting()调用Write ()而不是在基类名称前加上前缀(PenType::Write())?
4 - I think policy based design forces you to derive from classes which is semantically invalid. In the above code, a writer is derived from a pen only because writer uses a pen. But saying writer is a pen is semantically invalid. Is there any other better way to address this or I am missing something here?
4 - 我认为基于策略的设计迫使您从语义上无效的类派生。在上面的代码中,writer 是从钢笔派生出来的,因为 writer 使用钢笔。但是说作家是一支笔在语义上是无效的。有没有其他更好的方法来解决这个问题,或者我在这里遗漏了什么?
Any thoughts?
有什么想法吗?
回答by jalf
Here's how I would implement the class:
以下是我将如何实现该类:
template<class PenType>
class Writer
{
public:
Writer(const PenType& pen = PenType()) : pen(pen) {}
void StartWriting()
{
pen.Write();
}
private:
PenType pen;
};
This allows the user to pass a specific Pen object to the constructor, if it either doesn't have a default constructor, or you don't want it to be used, and second, it still allows you to omit the PenType object if you're happy to let it create one with the default constructor. The C++ standard library does the same in many classes (think of the allocators for container classes for example).
这允许用户将特定的 Pen 对象传递给构造函数,如果它没有默认构造函数,或者您不想使用它,其次,它仍然允许您省略 PenType 对象,如果您很高兴让它使用默认构造函数创建一个。C++ 标准库在许多类中执行相同的操作(例如,考虑容器类的分配器)。
I removed the inheritance. It didn't really seem to add anything (and might cause problems. You probably don't want the user of the Writer class to call the PenType::Write function directly. You could use private inheritance instead, but often, composition is a simpler and more conventional design.
我删除了继承。它似乎并没有真正添加任何东西(并且可能会导致问题。您可能不希望 Writer 类的用户直接调用 PenType::Write 函数。您可以使用私有继承来代替,但通常,组合是一个更简单和更传统的设计。
In general, policy-based design does not require inheritance. Adding it as a member works just as well. If you do go for inheritance, make it private so you don't get the problem you mentioned as #4.
一般来说,基于策略的设计不需要继承。将其添加为成员也同样有效。如果您确实要继承,请将其设为私有,这样您就不会遇到您在 #4 中提到的问题。
回答by Jasiu
This looks like a nice example of policy-based smart pointer implementation: link. Andrei Alexandrescudescribes policy-based smart pointer implementation in one of his books. As to your questions now. I have some experience in this stuff but not enough to take my words for granted:
这看起来像是基于策略的智能指针实现的一个很好的例子:link。Andrei Alexandrescu在他的一本书中描述了基于策略的智能指针实现。至于你现在的问题。我在这方面有一些经验,但还不足以将我的话视为理所当然:
Ad 1 & 4. I guess policy-based design is more about templates than inheritance. You write a template class and template arguments are policy classes, like that:
广告 1 和 4。我想基于策略的设计更多地是关于模板而不是继承。您编写一个模板类,模板参数是策略类,如下所示:
template<class FooPolicy, class BarPolicy>
class Baz {
// implementation goes here
};
Then you use methods from policy classes in your class:
然后你在你的班级中使用策略类的方法:
void Baz::someMethod(int someArg) {
FooPolicy::methodInit();
// some stuff
BarPolicy::methodDone();
}
I use static methods in this example because often policy doesn't require any state. If it does, you incorporate policy's state by composition, not by inheritance:
我在这个例子中使用静态方法是因为策略通常不需要任何状态。如果是,则通过组合而不是继承来合并策略的状态:
template<class FooPolicy, class BarPolicy>
class Baz {
private:
FooPolicy::State fooState; // might require 'typename' keyword, I didn't
// actually tried this in any compiler
// rest of the Baz class
};
Ad 2. You can write a template specialization - for a particular combination of main class and it's policies you can write a special version of any method or constructor, AFAIK:
广告 2. 您可以编写模板专业化 - 对于主类及其策略的特定组合,您可以编写任何方法或构造函数的特殊版本,AFAIK:
template <>
Baz<SomeConcreteFooPolicy, SomeConcreteBazPolicy>::Baz(someArgument)
: fooState(someArgument)
{
// stuff here
}
Hope it helps you a bit,
希望对你有一点帮助
Mike
麦克风
回答by stinky472
1 - Is this implementation looks correct? I mean is it really looks like a policy based design?
1 - 这个实现看起来正确吗?我的意思是它真的看起来像一个基于策略的设计吗?
Policy classes derive their usefulness from combining behaviors to produce a rich variety of combinations. When you have a single template parameter like this, it's not much of a policy class.
策略类从组合行为以产生丰富多样的组合中获得它们的用处。当您有一个这样的模板参数时,它就不是一个策略类。
2 - I can now hook any kind of pens to writer. But what will I do when I got a pen with no default constructor (only parameterized constructors)? How will I handle this situation?
2 - 我现在可以将任何类型的笔挂在作家身上。但是当我得到一支没有默认构造函数(只有参数化构造函数)的笔时,我该怎么办?我将如何处理这种情况?
Again, this is an odd example of a policy class. However, to directly answer your question, you can provide a constructor which accepts PenType. You should probably also avoid inheriting from PenType and store it as a member instead (no need to tightly couple your policy class with its policies).
同样,这是一个策略类的奇怪例子。但是,要直接回答您的问题,您可以提供一个接受 PenType 的构造函数。您可能还应该避免从 PenType 继承并将其存储为成员(无需将您的策略类与其策略紧密耦合)。
I guess compiler will replace PenType with InkPen. If yes, why I am not able to call just Write() from StartWriting() instead of prefixing base class name (PenType::Write())?
我猜编译器会用 InkPen 替换 PenType。如果是,为什么我不能只从 StartWriting() 调用 Write() 而不是在基类名称前加上前缀 (PenType::Write())?
When you inherit from a class template, you have to specify this->member or BaseClass::member.
从类模板继承时,必须指定 this->member 或 BaseClass::member。
4 - I think policy based design forces you to derive from classes which is semantically invalid. In the above code, a writer is derived from a pen only because writer uses a pen. But saying writer is a pen is semantically invalid. Is there any other better way to address this or I am missing something here?
4 - 我认为基于策略的设计迫使您从语义上无效的类派生。在上面的代码中,writer 是从钢笔派生出来的,因为 writer 使用钢笔。但是说作家是一支笔在语义上是无效的。有没有其他更好的方法来解决这个问题,或者我在这里遗漏了什么?
Store PenType as a member as suggested above. Always prefer composition to inheritance as it avoids the tight coupling relationship of inheritance.
按照上面的建议将 PenType 存储为成员。总是喜欢组合而不是继承,因为它避免了继承的紧密耦合关系。
回答by D.R.
I know this thread is old, but there is a major flaw in the initial post and this thread is one of the top results of Google...so:
我知道这个帖子很旧,但最初的帖子有一个重大缺陷,这个帖子是谷歌的最佳结果之一......所以:
Do not use public
inheritance for policy-based design! This would say "is-a" instead of "has-a" / "uses-a". You should therefore use private
inheritance!
不要将public
继承用于基于策略的设计!这会说“is-a”而不是“has-a”/“uses-a”。因此,您应该使用private
继承!