Skip to content
0

C++类模板

模板形式

c++
// 定义模板
template <typename T>
class ClassName {
private:
  T m_data;
public:
  ClassName(T);
}

// 实现模板
template <typename T>
ClassName<T>::ClassName(T t) 
{
  m_data = t;
}

// 使用模板类
ClassName<int> cn(1);
c++
template <typename T, int n>
class ClassName2 {}
c++
// 参数可带默认类型
template <typename T1, typename T2 = int>
class ClassName3 {}

模板可以作为基类,也可用作组件类,还可用作其他模板的类型参数。

提示

通常将模板的声明和定义放到同一个头文件中。

具体化

同函数模板,类模板的具体化也分为隐式实例化、显式实例化和显式具体化。

c++
// 编译器在需要对象之前,不会生成类的隐式实例化
ClassName2<int, 10> * ptr;  // 指针,还不需要对象,此步骤不会生成类
ptr = new ClassName2<int, 10>;  // 编译器将生成类定义,并根据该定义创建对象
c++
// 虽没有创建或提及类对象,编译器也将生成类声明(包括方法定义)
template class ClassName2<string, 10>;
c++
// 显式具体化的类模板定义,对特定类型,类模板有不同的行为(与函数模板用意相同)。
template <> class ClassName<char*> {};
c++
// 假设有一个通用的类模板定义
template <typename T1, typename T2> class TestClass {};

// 指定部分类型参数的类型,如指定T2为int类型
template <typename T1> class TestClass<T1, int> {};

成员模板

模板可以作为结构体、类或模板类的成员。

c++
template <typename T>
class Beta
{
private:
    template <typename V>  // 嵌套模板作为模板类的成员
    class Hold
    {
    private:
        V val;
    public:
        Hold(V v=0): val(v) {}
        void show() const { cout << val << endl; }
        V value() const { return val; }
    };

    Hold<T> q;
    Hold<int> n;
public:
    Beta(T t, int i): q(t), n(i) {}

    template<typename U>  // 模板方法
    U blab(U u, T t) { return (q.value() + n.value()) * u / t; }

    void show() const { q.show(); n.show(); }
};
c++
template<typename T>
class Beta
{
private:
    template <typename V>
    class Hold;
    Hold<T> q;
    Hold<int> n;
public:
    Beta(T t, int i) : q(t), n(i) {}

    template<typename U>
    U blab(U u, T t);

    void show() const { q.show(); n.show(); }
};

template <typename T>
template <typename V>
class Beta<T>::Hold
{
private:
    V val;
public:
    Hold(V v = 0) : val(v) {}
    void show() const { cout << val << endl; }
    V value() const { return val; }
};

template <typename T>
template <typename U>
U Beta<T>::blab(U u, T t)
{
    return (n.value() + q.value()) * u / t;
}

模板作为参数

c++
template <template <typename T> typename U, typename V>
class Crab {
private:
    U<int> s1;
}
// ...
Crab<ClassName, int> c1;

U作为模板的参数,其本身也是一个类模板,类U模板的的声明是template <typename T>,实例对象c1中的ClassName模板类要符合此声明。U<int>将被替换成ClassName<int>

模板类和友元

  • 非模板友元:在模板类中将一个常规函数声明为友元。
  • 约束模板友元:友元的类型取决于类被实例化时的类型,即类模板的参数类型作为友元函数模板参数类型的一部分。
  • 非约束模板友元:友元的所有具体化都是类的每一个具体化的友元,即类模板的参数类型和友元函数模板的参数类型无关。
c++
template <typename T>
class HasFriend
{
public:
    HasFriend(const T& t) : item(t) { ct++; }
    ~HasFriend() { ct--; }
    friend void counts();
    friend void reports(HasFriend<T>&);
private:
    T item;
    static int ct;
};


template <typename T>
int HasFriend<T>::ct = 0;
void counts()
{
    cout << "int count: " << HasFriend<int>::ct << ";";
    cout << "double count: " << HasFriend<double>::ct << endl;
}
void reports(HasFriend<int>& hf)
{
    cout << "HasFriend<int>: " << hf.item << endl;
}
void reports(HasFriend<double>& hf)
{
    cout << "HasFriend<double>: " << hf.item << endl;
}

int main()
{
    cout << "No Objects declared: ";
    counts();
    HasFriend<int> hfi1(10);
    cout << "After hfi1 declared: ";
    counts();
    HasFriend<int> hfi2(20);
    cout << "After hfi2 declared: ";
    counts();
    HasFriend<double> hfdb(10.5);
    cout << "After hfdb declared: ";
    counts();

    reports(hfi1);
    reports(hfi2);
    reports(hfdb);
}
c++
template <typename T> void counts();
template <typename T> void reports(T&);

template <typename TT>
class HasFriend
{
public:
    HasFriend(const TT& t) : item(t) { ct++; }
    ~HasFriend() { ct--; }
    friend void counts<TT>();
    friend void reports<HasFriend<TT>>(HasFriend<TT>&);
private:
    TT item;
    static int ct;
};


template <typename T>
int HasFriend<T>::ct = 0;

template <typename T>
void counts()
{
    cout << "template size: " << sizeof(HasFriend<T>) << endl;
    cout << "template counts: " << HasFriend<T>::ct << endl;
}

template <typename T>
void reports(T& hf)
{
    cout << hf.item << endl;
}

int main()
{
    counts<int>();
    HasFriend<int> hfi1(10);
    HasFriend<int> hfi2(20);
    HasFriend<double> hfdb(20.5);
    reports(hfi1);
    reports(hfi2);
    reports(hfdb);
    cout << "counts<int>() output: ";
    counts<int>();
    cout << "counts<double>() output: ";
    counts<double>();
}
c++
template <typename T>
class ManyFriend
{
private:
    T item;
public:
    ManyFriend(const T& t): item(t) {}
    template <typename C, typename D> friend void show(C&, D&);
};


template <typename C, typename D> void show(C& c, D& d)
{
    cout << c.item << ", " << d.item << endl;
}

int main()
{
    ManyFriend<int> hfi1(10);
    ManyFriend<int> hfi2(20);
    ManyFriend<double> hfdb(20.5);
    show(hfi1, hfi2);
    show(hfdb, hfi2);
}