4

在我工作的代码库的尘土飞扬的角落里,我遇到了一个如下所示的类层次结构:

class Base1
{
  int base1;
};

class Base2
{
  int base2;
};
template <typename T> class A : public Base1
{
      T _specialT;
};
template <> class A<int> : public Base2
{
      int _special;
};

在 A 的专业化中使用 Base2 让我感到惊讶。我一直在四处寻找以了解它的确切含义,但找不到任何此类设计的示例或讨论。

在我看来,这会导致 A 从 Base1 和 Base2 继承,而 A 的其他非专用用途将仅从 Base1 继承。这给我留下了几个问题:

  1. 我理解正确吗?
  2. 以这种方式添加到层次结构中是否有任何不明显的警告?你为什么要这样做?
  3. 有时这会被认为是好的设计吗?
4

3 回答 3

4
  1. 不,主要类模板继承自Base1,并且只有特化<int>继承自Base2(并且Base2仅继承自)。

不知道使用它的上下文,我无法回答 2. 或 3。

在模板元编程中,您经常可以看到源自不同类型的专业化。例如:

template<typename T, typename U>
struct is_same : std::false_type {};

template<typename T>
struct is_same<T,T> : std::true_type {};

这是完全有效的事情。做的好不好,完全取决于要解决的问题。

于 2013-08-14T09:35:33.623 回答
2

模板的特化在代码方面完全独立于正常情况。所以A<int>不会同时从Base1and派生Base2,只是从Base2.

在某些情况下,专业化是好的设计。当然,从您的抽象示例中无法判断这是否是一个。

于 2013-08-14T09:35:09.850 回答
2

请记住,类模板的不同实例化是不同的独立类。模板的特殊化不会在一般情况下添加任何东西,它们会完全取代它。

因此,A<int>是一个类,它派生自Base2并具有一个名为 的 int 成员_specialA<double>并且A<char>是两个独立的不同类,它们恰好派生自Base1并且各自具有一个类型为 double 和 char 的成员,分别名为_specialT

所以:

  1. 从您的问题看来,您没有正确理解它。
  2. 有一些警告,特别是如果特化不是直接在基本模板之后而是在另一部分定义的。如果维护者看到 A 的一般定义并尝试Base1在一个A<int>(或使用_specialT成员)上使用某些方法,由于他没有看到特化而导致编译器错误,这将是一个惊喜。一个非常流行的例子是std::vector<bool>标准中的专业化,它的行为与“正常”不同,std::vector并且被广泛认为是损坏的。
  3. 有时有些人认为这是好的设计,有时这样的设计甚至被很多人认为是好的。然而,设计有时是一种品味问题,当涉及到模板及其不那么典型的用例时,许多人认为意想不到的事情,比如专业化中的不同基类是不好的风格,或者至少是“黑色模板魔法”,例如当它用于模板元编程时。

这种模式(来自不同基础的专业化)经常用于模板元编程。一个(非常)简单的例子:

template <class T>
struct is_int_or_double : std::false_type
{};

template <>
struct is_int_or_double<int> : std::true_type //another base class!
{};

template <>
struct is_int_or_double<double> : std::true_type //another base class!
{};
于 2013-08-14T09:55:43.490 回答