LINUX.ORG.RU

Вызов шаблонного метода базового класса C++

 , , ,


0

2

Доброго времени суток.

Есть простенький код на С++ который не компилируется.

Базовый класс:

// base.h

template<class T>
class Base
{
public:
    T getData();
    virtual T prepareData() = 0;
};

// base.cpp

#include "base.h"

template<class T>
T Base<T>::getData()
{
    return prepareData();
}

Дочерний класс:

// target.h

#include <QList>
#include "base.h"

class Target : public Base<QList<int> >
{
public:
    Target();
    virtual QList<int> prepareData();
};

// target.cpp

#include "target.h"

Target::Target() :
    Base<QList<int> >()
{
}

QList<int> Target::prepareData()
{
    return QList<int>();
}

Место вызова:

// main.cpp

#include "target.h"
#include <QList>

int main(int arcv, char** argc) {
     QList<int> d = Target().getData(); // undefined reference to `Base<QList<int> >::getData()'
     return 0;
}

Как я понимаю, дочерний класс должен включить в себя методы базового класса и развернуть шаблоны в конкретные типы (чего, как я понял не произошло). ЧЯДНТ?

Компилятор не генерирует никакого кода из шаблонной функции по месту её определения. Вместо этого он его генерирует по месту использования. Но в том месте где ты используешь шаблонную функцию, её определение не доступно. Вот и получается.

KblCb ★★★★★ ()
Ответ на: комментарий от anonymous

Лучше добавь в cpp-файл строку template class Base<int>;

И соответственно со всеми остальными типами, которые будешь подставлять в шаблон.

Y ★★ ()
Ответ на: комментарий от Y

Explicit instantiation его не спасёт. Перенести тело в хидер - правильный выход.

И, кстати,

template<> class Base<QList<int> > {};

тогда уж.

anonymous ()
Ответ на: комментарий от Y

А, сильно торможу, прошу прощения.

template class Base<QList<int> > ;

Да. Но всё равно не поможет. Это же всё равно надо совать в сишник, где тело лежит. Честно говоря я в этом вижу мало смысла. Лучше и проще тело в хидер сунуть (и не лазать потом новые определения добавлять).

anonymous ()

Почитай про модель включения, их несколько типов, но самый распростаненный это все в хедер засунуть
не знаю какой это пункт стандарта -)

Boy_from_Jungle ★★★★ ()

Дочерний класс ничего не разворачивает. Разворачивает компилятор. Это первое.

Второе. Компилятор обрабатывает исходники по одному. В другой файл он лезет только в том случае, когда этот другой подключён к обрабатываемому include-ом (или цепочкой include-ов).

Теперь подумай: вот у тебя три .cpp-файла. Какой из них компилятор должен обрабатывать в данный момент, чтобы соорудить правильный метод getData? И какие файлы он при этом видит?

Miguel ★★★★★ ()
Ответ на: комментарий от anonymous

А мне наоборот больше нравится такой стиль. Так как обыкновенно шаблонный класс не бывает абсолютно универсальным.

Y ★★ ()
Ответ на: комментарий от anonymous

Перенеси определение getData в хедер.

Спасибо помогло.

Почитай про модель включения

Буду очень признателен, если мне посоветуют книгу в которой эта тема описана «человеческим» (возможно, даже русским) языком. Для чтения стандартов у меня уровень не тот.

anonymous327 ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.