How to define different types for the same class in C++
我想有几种类型共享相同的实现,但在C ++中仍然是不同的类型。
为了用一个简单的例子来说明我的问题,我想有一个Apples,Oranges和Bananas的类,它们都具有相同的操作和相同的实现。 我希望他们有不同的类型,因为我希望通过类型安全来避免错误。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class Apple { int p; public: Apple (int p) : p(p) {} int price () const {return p;} } class Banana { int p; public: Banana (int p) : p(p) {} int price () const {return p;} } class Orange ... |
为了不复制代码,看起来我可以使用基类Fruit并从中继承:
1 2 3 4 5 6 7 8 9 10 | class Fruit { int p; public: Fruit (int p) : p(p) {} int price () const {return p;} } class Apple: public Fruit {}; class Banana: public Fruit {}; class Orange: public Fruit {}; |
但是,构造函数不是继承的,我必须重写它们。
是否有任何机制(typedef,templates,inheritance ...)可以让我轻松拥有不同类型的同一个类?
一种常见的技术是使用类模板,其中模板参数仅用作唯一标记("标记")以使其成为唯一类型:
1 2 3 4 5 6 7 8 9 10 | template <typename Tag> class Fruit { int p; public: Fruit(int p) : p(p) { } int price() const { return p; } }; using Apple = Fruit<struct AppleTag>; using Banana = Fruit<struct BananaTag>; |
请注意,甚至不需要定义标记类,它足以声明唯一的类型名称。这是有效的,因为标签实际上并未在模板中的任何位置使用。您可以在模板参数列表中声明类型名称(帽子提示为@Xeo)。
1 | typedef Fruit<struct AppleTag> Apple; |
如果常见功能占用了大量代码,那么不幸的是,在最终的可执行文件中引入了相当多的重复代码。这可以通过具有实现该功能的公共基类,然后具有从中派生的特化(您实际实例化)来防止。
不幸的是,这需要你重新实现所有不可继承的成员(构造函数,赋值...),这会增加一些小的开销 - 所以这只适用于大类。这里它适用于上面的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | // Actual `Fruit` class remains unchanged, except for template declaration template <typename Tag, typename = Tag> class Fruit { /* unchanged */ }; template <typename T> class Fruit<T, T> : public Fruit<T, void> { public: // Should work but doesn’t on my compiler: //using Fruit<T, void>::Fruit; Fruit(int p) : Fruit<T, void>(p) { } }; using Apple = Fruit<struct AppleTag>; using Banana = Fruit<struct BananaTag>; |
使用模板,并使用每个水果的特征,例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 | struct AppleTraits { // define apple specific traits (say, static methods, types etc) static int colour = 0; }; struct OrangeTraits { // define orange specific traits (say, static methods, types etc) static int colour = 1; }; // etc |
然后有一个
1 2 3 4 5 6 7 8 9 10 11 12 | template <typename FruitTrait> struct Fruit { // All fruit methods... // Here return the colour from the traits class.. int colour() const { return FruitTrait::colour; } }; // Now use a few typedefs typedef Fruit<AppleTraits> Apple; typedef Fruit<OrangeTraits> Orange; |
可能有点矫枉过正! ;)
- C ++ 11将允许构造函数继承:使用C ++基类构造函数?
-
否则,您可以使用模板来实现相同的目的,例如,
template class Fruit;
还有BOOST_STRONG_TYPEDEF。