C++模板类专业化:为什么需要重新实现常用方法

Jai*_*ime 14 c++ templates specialization

在样本中:

#include <iostream>

using namespace std;

class B
{
public:
    virtual void pvf() = 0;
};

template <class T>
class D : public B
{
public:
    D(){}

    virtual void pvf() {}

private:
    string data;
};

template <>
class D<bool> : public B
{
public:
    D();

    virtual void pvf(){ cout << "bool type" << endl; }
};

int main()
{
    D<int> d1;
    D<bool> d2;
}
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

test.cpp:(.text+0x1c): undefined reference to `D<bool>::D()'
Run Code Online (Sandbox Code Playgroud)

请注意,我不仅仅专门研究D()的原因是我想D<T>::data在这种D<bool>情况下消除字符串的需要.

为什么我需要重新实现D()D<bool>?好像应该有一种方法让我告诉编译器使用该版本D<T>.

有没有办法像这样做一个简单的专业化而不必重新实现方法?

Mik*_*our 17

类模板的每个特化都给出了一个不同的类 - 它们不会彼此共享任何成员.由于您已明确专门化了整个类,因此您无法从模板中获取任何成员,并且必须全部实现它们.

您可以明确地专门化个别成员,而不是整个类:

template <> void D<bool>::pvf(){ cout << "bool type" << endl; }
Run Code Online (Sandbox Code Playgroud)

然后,D<bool>仍将包含您未明确专门化的类模板的所有成员,包括默认构造函数.


Pla*_*aHH 11

不,那里没有.

专业化的行为与继承性非常不同.它与通用模板版本无关.

使用/实例化模板时,编译器将创建新的类型名称,然后查找如何定义此类型.当它找到特化时,则将其作为新类型的定义.如果没有,则采用通用模板并实例化它.

因此它们没有连接,你只是在编写一个全新的类,只是有一个特殊的名称供编译器查找,以防有人使用/实例化模板以在该名称下找到它.

  • 那是不幸的 (12认同)

Ker*_* SB 5

问题是你错误的假设,即和之间有任何共同点.模板实例是类型,两个不同的实例是两种不同的类型,故事结尾.只有这样,同一模板的实例才具有正式相似的代码,但通过专业化,您可以定义任何您喜欢的类型.简而言之,您明确定义的每种类型都是完全独立的,并且在专用模板实例之间没有共性,即使它们碰巧具有相同的名称.D<A>D<B>

例如:

template <typename T> struct Foo
{
    T & r;
    const T t;
    void gobble(const T &);
    Foo(T *);
};

template <> struct Foo<int>
{
    std::vector<char> data;
    int gobble() const;
    Foo(bool, int, Foo<char> &);
};
Run Code Online (Sandbox Code Playgroud)

这些类型Foo<char>并且Foo<int>彼此无关,并且没有理由为什么一个部分的任何部分应该在另一个内部有任何用途.

如果要分解常见功能,请使用私有继承:

template <typename> struct D : private DImpl { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

  • @Jaime:嗯,我认为除了"因为这就是C++的设计方式"之外还有一个答案,但也要考虑到普通类是不可能的,它实际上是完全相同的论点:为什么不能一个类继承另一个类的部分实现?好吧,它*可以*通过使用继承:-)(正如我在答案中建议的那样.) (2认同)