[c++] Проблема при линковке - unresolved variable
Код, пожалуйста. Если он говорит, что unresolved variable, то мне кажется, что у тебя что-то не так с синтаксисом.
name.h
#ifndef NAME_H
#define NAME_H
template <class DATA> class CLASS_NAME{
public:
void Func;
};
#endif
name.cpp
#include "name.h"
template<class DATA> void CLASS_NAME<DATA>::Func
{
}
main.cpp
#include "name.h"
class data{
public:
doouble x;
};
int main{
CLASS_NANE<data> ob;
ob.Func;
return 0;
}
![](/images/graemlins/confused.gif)
Блин, ошибочка вышла. Со спеллингом все нормально - я проверял, это когда пост писал очепятался
Ну, а ошибка какая вылезает?
unresolved variable - template<class data> void CLASS_NAME<data>::Func
кажется так...
То, что ты пытаешься сделать, называется экспортом шаблонов. Он не реализован в твоем компиляторе.
Это, что, тогда получается в своем шаблонном классе я не смогу определить ни одной функции-члена данного шаблонного класса? Тогда зачем мне такой класс? Это как-то странно выглядит... Неужели совсем ничего нельзя сделать?
Можно в хедер перенести.
Вау! Точно,это помогает! Спасибо большое!
Вывод: либо весь шаблонный класс вместе с методами должен располагаться в h-файле (и, соответственно, содержать только inline-методы либо использовать явную инстанциацию (и ограничиться фиксированным набором значений аргументов шаблона либо использовать компилятор с поддержкой экспорта шаблонов, либо не использовать здесь шаблонный класс.
либо весь шаблонный класс вместе с методами должен располагаться в h-файле (и, соответственно, содержать только inline-методы)Это не связанные вещи. Т.е. описание шаблонной функции должно быть в хедере, но при этом она не обязана быть inline, если ты ее таковой не объявишь.
Да, но если этот файл включается более, чем в одном месте, при наличии не-inline функций будут проблемы при сборке (если только во всех классах не производится инстанцирование к разным типам, но на это закладываться плохо).
Я хочу тебе сказать, что у меня таких проблем со сборкой не было, MSVC8
Это не связанные вещи. Т.е. описание шаблонной функции должно быть в хедере, но при этом она не обязана быть inline, если ты ее таковой не объявишь.1. если функция определена в теле класса, то она автоматически является inline (по стандарту)
2. функция определенная вне тела класса не будет конечно inline, если ее не объявить таковой.
3. функция определенная в хедере по стандарту обязана быть inline (т.е. прогер должен явно или неявно объявить ее таковой в противном случае при включении данного хедера в разные трансляции нарушается "one definition rule". (это может приводить или не приводить к проблеме в зависимости от компилятора или версии оного)
То, что ты пытаешься сделать, называется экспортом шаблонов. Он не реализован в твоем компиляторе.это называлось бы экспортом шаблонов, если бы перед определением функции-члена стояло ключевое слово export, а так это называется просто ошибка (не синтаксическая ошибка, а просто функция доступна только в той трансляции, в которой определена, а используется в другой трансляции - и это так и должно быть и с точки зрения стандарта языка и с точки зрения большинства компиляторов).
Каким образом оно нарушается, если объявления буква в букву повторяются?
Кстати, MSVC8 на это дело ругается. Только что проверял.
А почему, собственно, обязательно повторяются?Мы сейчас говорим о том, что ты определяешь тело шаблонной функции или класса в хедере. Если при этом ты включаешь хедер в различные единицы трансляции, у тебя содержание хедера каждый раз будет произвольно меняться? Думаю, что нет.
Почему бы и нет? Макросы никто не отменял.
Кстати, MSVC8 на это дело ругается. Только что проверялНа какое дело? На определение шаблонной функции в хедере? А разве не писал, что у него работает?
Кажется, функция не обязана являться inline. Она может быть локально вкомпилирована в каждый объектный файл в виде отдельной функции. Но это техника, конечно.
Вообще-то, я сейчас говорю о том, что если специально это правило не нарушать, то оно не нарушается, и вполне стандартным является объявление не инлайн шаблонных функций в хедере.
То, что ты говоришь о макросах - естественно, что если ты хочешь создать себе проблем, то ты найдешь способ это сделать.
Ругается на определение не-inline функции в хедере, который включен в нескольких файлах. У -а, небось, он включен только в один файл, или описание размещено в теле класса.
Как раз стандартным оно не является (см. выше). Два объявления (пусть даже и одинаковых) - это все-таки не одно объявление. Как ты предлагаешь линкеру выяснять, являются ли определения двух функций с идентичными именами одинаковыми? Вполне возможно, что сгенерированный компилятором код будет разным.
Каким образом оно нарушается, если объявления буква в букву повторяются?вообще-то ты прав - не нарушается
думал, что нарушается согласно пункту 3 (который касается как выяснилось только обычных функций, а не шаблонных но потом увидел, что согласно пункту 5 функции-члены шаблонных классов могут быть определены в разных трансляциях (одинаково).
![](/images/graemlins/smile.gif)
testclass.h
class A {
void func;
};
void A::func
{
}
//----------------------
hTest.cpp
#include "testclass.h"
int main
{
return 0;
}
//----------------------
other.cpp
#include "testclass.h"
template.h
template <typename T>
T echo(T var)
{
return var;
}
double_echo.h
int double_echo(int var);
double_echo.cpp
#include "double_echo.h"
#include "template.h"
int double_echo(int var)
{
return echo(var);
}
test.cpp
#include <iostream>
#include "template.h"
#include "double_echo.h"
using namespace std;
int main
{
int a = 0, b;
b = echo(a);
if (b == double_echo(a
cout << "I am a luser";
else
cout << "I am lucky";
}
И где у тебя testclass.h описан?
нестатические функции-члены шаблонных классов могут быть определены в разных трансляциях (одинаково)Хм, а как тогда быть со статическими шаблонными членами?
Пардон, опечатался. Первый файл не cpp, а h
template.h
template <typename T>
class ZZ
{
public:
static T echo(T var);
};
template <typename T>
T ZZ<T>::echo(T var)
{
return var;
}
double_echo.h
int double_echo(int var);
double_echo.cpp
#include "double_echo.h"
#include "template.h"
int double_echo(int var)
{
return ZZ<int>::echo(var);
}
test.cpp
#include <iostream>
#include "template.h"
#include "double_echo.h"
using namespace std;
int main
{
int a = 0, b;
b = ZZ<int>::echo(a);
if (b == double_echo(a
cout << "I am a luser";
else
cout << "I am lucky";
}
Собирается, запускается, работает.
Лол, у тебя класс не шаблонный.
Кажется, функция не обязана являться inline. Она может быть локально вкомпилирована в каждый объектный файл в виде отдельной функции. Но это техника, конечно.я использую термин inline-функция как термин из стандарта
так вот: как inline-функция, так и не-inline-функция может быть как локально вкомпилирована в каждый объектник (или только в один объектник так и быть встроена в место ее использования - это зависит исключительно от реализации.
Является ли она inline или нет определяется исключительно синтаксисом ее объявления и определения, а не тем куда она вкомпилирована.
Это не предмет дискуссии, а просто терминология такая (из стандарта ISO/IEC-14882).
Хм, а как тогда быть со статическими шаблонными членами?да так же
написано просто "member function of a class template"
это я просто сослался на данную конкретную ситуацию, но для большей общности подредактировал тот пост (убрал слово "нестатические")
Мне кажется, ты ошибаешься насчет статических функций,я не могу насчет них ошибаться, поскольку я насчет них ничего не утверждал
уже я пост поправил
Собирается, запускается, работает.наверно ты и сам догадываешься насколько это наивно приводить в качестве аргумента.
я могу такие кошмарные проги, которые "работают" (на конкретном компиляторе) привести, что офигеешь.
Работающие проги, и корректные согласно стандарту проги - это совсем разные вещи (общеизвестны примеры как работающих, но некорректных, так и корректных, но неработающих).
А уж когда речь о таких тонких материях как соответствие "one definition rule", диагностика которого стандартом вообще не требуется (т.е. все может оказаться целиком на совести программиста в полном соответствии со стандартом то тем более.
Угу, согласен.
А почему, собственно, обязательно повторяются? Теоретически они могут оказаться различными. А компилятор не обязан их сравнивать.вот если определения одной и той же функции (шаблонной или inline) окажутся разными в разных трансляциях - это и будет нарушением "one definition rule", а если определения одной и той же функции синтаксически идентичны, то нарушения нет.
И да: компилятор не обязан диагностировать (замечать) нарушение "one definition rule", соблюдение оного - обязанность программиста.
Нарушение "one definition rule" может не приводить к проблемам, может вызывать ошибку, а может приводить к очень экзотическим проблемам с неожиданными проявлениями (все от реализации зависит).
Оставить комментарий
internet-mail
Я использую MSVC-компилятор. Определяю в одном файле (name.h) некоторый шаблонный класс, далее в другом файле (name.cpp) определяю функцию-член определенного ранее класса, которую вызываю в третьем файле (main.cpp). При линковке возникает ошибка LNK2001 - unresolved variable 'имя_функции-члена_моего_класса '.... Кто знает, что делать в таком случае? Я уж даже не знаю - вроде вcе правильно делаю...