Clase / función de plantilla C ++, archivo de encabezado separado del archivo de origen

Separe los archivos de origen que contienen plantillas de los archivos de encabezado

La clave está en la instanciación explícita de la plantilla.

solución

Función de plantilla para separar archivos fuente

  1. Escriba .hy .cpparchive de la manera habitual , pero preste atención a la template <typename T>declaración agregada ;
  2. Al .cppfinal del archivo, agregue el 显式实例化código de plantilla , como:
// 显式实例化,注意,`template`之后没有`<>`,若添加则会报错!
// 每种将被使用的类型,均需要进行显式实例化
template void A::show(int &&);
template void A::show(double &&);
template void A::show(bool &&);

Archivo fuente separado de clase de plantilla

  1. Escriba la clase de plantilla .hy el .cpparchivo por separado , preste atención a la template <typename T>declaración agregada ;
  2. Al .cppfinal del archivo, agregue el 显式实例化código de la clase , como:
// 只需要class的显式实例化即可,不需要再写其成员函数的显式实例化代码
template class Base<QLabel>;
  1. Al .hfinal del archivo de otras clases que usan esta clase de plantilla , agregue la clase de plantilla externa 显式实例化声明(solo una externpalabra clave más ):
// 添加这行代码的目的,其实是为了消除编译警告。即便删掉它,也不会导致编译错误
extern template class Base<QLabel>;

Lo anterior es una breve descripción del método para separar el archivo fuente y el archivo de encabezado de la función / clase de plantilla Es inevitable que haya omisiones. Si aún tiene preguntas, puede continuar viendo casos específicos.


Código de muestra

Función de plantilla

  • th
#ifndef _T_H
#define _T_H

class A
{
    
    
public:
        template <typename T>
        void show(T &&t);
};

#endif // _T_H
  • t.cpp
#include "t.h"
#include <iostream>
using namespace std;


template <typename T>
void A::show(T &&t)
{
    
    
        string info = typeid(t).name();
        cout << info << endl;
}

// 显式实例化,注意,`template`之后没有`<>`,若添加则会报错!
template void A::show(int &&);
template void A::show(double &&);
template void A::show(bool &&);
  • main.cpp
#include <iostream>
#include "t.h"
using namespace std;


int main()
{
    
    
        A a;
        a.show(1);
        a.show(3.4);
        a.show(true);
}

Simplemente compile directamente:

a: t.cpp main.cpp
	g++ $^ -o $@ -std=c++17

correr:

./a
​```output
i
d
b
​```end

Clase de plantilla

Clase de plantilla (clase base)

  • archivo de cabeza
#include <QObject>
class QLabel;

template <typename T>
class Base : public QObject
{
    
    
public:
    Base(QObject *parent = nullptr);
    virtual ~Base() override;

    void add(T *t);
    void remove(T *t);
    void remove(int idx);
    T *find(int idx) const;
    
protected:
    QList<T *> _listItems;

};
  • Archivo fuente
#include "base.h"
#include <QLabel>


template <typename T>
Base<T>::Base(QObject *parent)
    : QObject(parent)
{
    
    
    // Do nothing
}

template <typename T>
Base<T>::~Base()
{
    
    
    qDeleteAll(_listItems);
    _listItems.clear();
}

template <typename T>
void Base<T>::add(T *t)
{
    
    
    _listItems.append(t);
}

template <typename T>
void Base<T>::remove(T *t)
{
    
    
    _listItems.removeAll(t);
}

template <typename T>
void Base<T>::remove(int idx)
{
    
    
    _listItems.removeAt(idx);
}

template <typename T>
T *Base<T>::find(int idx) const
{
    
    
    return _listItems.at(idx);
}


/************************************ Explicit Instantiate *****************************/
template class Base<QLabel>;

Clase derivada ordinaria de clase de plantilla

  • archivo de cabeza
#include "base.h"
class QLabel;

class Son : public Base<QLabel>
{
    
    
public:
    Son(QObject *parent = nullptr);
    virtual ~Son() override;

protected:
    void init();

};

/********************************** Explicit Instantiate *****************************/
extern template class Base<QLabel>;

  • Archivo fuente
#include "son.h"
#include <QLabel>

Son::Son(QObject *parent)
    : Base<QLabel>(parent)
{
    
    
    init();
}

Son::~Son()
{
    
    
    // Do nothing
}

void Son::init()
{
    
    
    add(new QLabel());
    remove(new QLabel);
    remove(123);
    find(321);
}


Formas de eliminar las advertencias del compilador de clases derivadas de plantillas

  1. Al cppfinal del archivo de la clase base de la clase de plantilla , agregue el código de instanciación explícito:
template class Base<QLabel>;
  1. Al .cppcomienzo del archivo de la clase base de la clase de plantilla , agregue un archivo de inclusión:
#include <QLabel>
  1. .hAgregue el código de declaración externa al final del archivo de la clase de plantilla clase derivada general :
extern template class Base<QLabel>;

Supongo que te gusta

Origin blog.csdn.net/gkzscs/article/details/108662174
Recomendado
Clasificación