Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Шаблоны в Visual C++, Ошибка линковки 
:(
    Опции темы
Dark Elf
  Дата 31.1.2005, 13:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 576
Регистрация: 26.12.2003
Где: Брисбен

Репутация: нет
Всего: 10



Здравствуйте все!

У меня тут такая проблема: я объявляю шаблонный класс в Visual C++ пишу конструктор: в файле .h:
Код

CArray2D(T* source, unsigned width, unsigned height);
virtual ~CArray2D();

Потом пишу в файле .cpp:
Код

template <class T> CArray2D<T>::CArray2D(T* source, unsigned w, unsigned h)
{
width = w;
height = h;
unsigned size = width * height;
data = new T[size];
for (unsigned index = 0;index < size;index++)
{
 data[index] = source[index];
}
}
template <class T> CArray2D<T>::~CArray2D()
{
if (data)
{
 delete[] data;
}
}

При компиляции ошибок никаких не выдается, но при попытке создать экземпляр данного класса вот так:
Код

CArray2D <int> arr(f,5,5);

выдаются следующие ошибки линковки:
unresolved external symbol "public: virtual __thiscall CArray2D<int>::~CArray2D<int>(void)" (??1?$CArray2D@H@@UAE@XZ)
unresolved external symbol "public: __thiscall CArray2D<int>::CArray2D<int>(int *,unsigned int,unsigned int)" (??0?$CArray2D@H@@QAE@PAHII@Z)

Причём тут __thiscall мне вообще непонятно - это ж ключевое слово зарезервировано в VC6 для будущего использования и его использование вызывает ошибку...

Заранее благодарен за помощь

Это сообщение отредактировал(а) Dark Elf - 31.1.2005, 13:02


--------------------
PM MAIL WWW ICQ Skype GTalk Jabber MSN   Вверх
maxim1000
Дата 31.1.2005, 13:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 1
Всего: 110



описание конструктора и создание экземпляра класса - в одном cpp или в разных?


--------------------
qqq
PM WWW   Вверх
Dark Elf
Дата 31.1.2005, 16:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 576
Регистрация: 26.12.2003
Где: Брисбен

Репутация: нет
Всего: 10



В разных .cpp - в частности создание экземпляра класса в функции main... это может что-то менять?
(заголовок "Array2D.h" естественно подключён smile)


--------------------
PM MAIL WWW ICQ Skype GTalk Jabber MSN   Вверх
bel_nikita
Дата 31.1.2005, 16:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Эксперт
Сообщений: 2304
Регистрация: 12.10.2003
Где: Поезд №21/22 ( ст . Прага )

Репутация: 2
Всего: 47



Объявляй и определяй все в *.H


--------------------
user posted image — регистрация доменов от 150 руб.
PM MAIL WWW ICQ   Вверх
chipset
Дата 31.1.2005, 16:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 4071
Регистрация: 11.1.2003
Где: Seattle, US

Репутация: 1
Всего: 165



Шаблоны сделаны так что реализацию нельзя отделять от обьявления. Это значит что все надо обьявлять в *.h.
Я кстати тоже споткнулся очень больно об это один раз ;)


--------------------
Цитата(Jimi Hendrix)
Well, I stand up next to a mountain
And I chop it down with the edge of my hand
PM MAIL WWW   Вверх
maxim1000
Дата 31.1.2005, 17:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 1
Всего: 110



да, может...
как работают шаблоны:
1. программист пишет (неважно где: в cpp или в h-файле, все равно в конце концов все оказывается в cpp) параметризированный код
этот параметризированный код НЕ КОМПИЛИРУЕТСЯ
2. компилятор смотрит, CArray2D каких типов нужны и для каждого такого случая сам пишет код в cpp-файл, подставляя нужный тип
таким образом, если, к примеру, основную часть размера программы составляет реализация массива (а используется он только для int), то при написании одной простой строки Array<char> размер программы увеличится приблизительно в два раза...
3. ну и еще одно важное замечание: все cpp-файлы компилируются ОТДЕЛЬНО
теперь ставим себя на место компилятора:
1. компилирует он файл с реализацией шаблона, смотрит, а, собственно, для каких типов тебе шаблон нужен, и не находит (в этом cpp он ни для какихтипов не нужен), вот он и не генерирует абсолютно никакого кода
2. компилирует он cpp-файл, в котором идет использование шаблона смотрит, там шаблон описан (h-файл ведь подключается), значит, он должен быть где-то снаружи, делает ссылку, которая указывает на несуществующий код, что и замечает линковщик

как починить (два способа):
1. создать переменную типа CArray2D <int> в cpp-файле, содержащем реализацию шаблона, это приведет к появлению нужного кода, и ссылка в другом файле уже не будет "в никуда"
2. разместить реализацию шаблона в h-файле
вообще-то я считаю размещение кода в h-файле дурным тоном, но есть два случая, когда я готов с ним мириться: макросы и шаблоны

какие отличия между этими способами:
(1) выглядит очень криво: для каждой спецификации шаблона нужно будет описывать переменную этого типа в соответствующем файле, это означает, что при каждом новом способе использования шаблона придется лезть в этот файл и добавлять что-то там... это очень плохо...
(2) выглядит очень привлекательно: для того, чтобы использовать шаблон, достаточно просто подключить соответствующий h-файл и наслаждаться реализованной кем-то функциональностью

НО: есть одна деталь: почему не очень хорошо помещать код в h-файл?
очень просто - h-файл вставляется в каждый cpp-файл, в котором будет написано #include, а это означает, что и компилироваться он будет каждый раз, вот и получается, что каждый файл, который использует Array<int>, на самом деле сам же его и реализует (подключением h-файла), т.е. один и тот же код будет присутствовать в куче obj-файлов после компиляции... это плохо, если, к примеру, реализация составляет ощутимую часть размера приложения... однако, вполне возможно, что создатели компиляторов (а точнее, линковщиков) все это уже продумали, и в результате остается только одна копия кода... как-нибудь на досуге проверю...
Добавлено @ 17:09
ого... тут уже наотвечали, пока я писал... все равно, надеюсь, это окажется полезным smile


--------------------
qqq
PM WWW   Вверх
maxim1000
Дата 31.1.2005, 18:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 1
Всего: 110



небольшое дополнение:
Цитата
однако, вполне возможно, что создатели компиляторов (а точнее, линковщиков) все это уже продумали, и в результате остается только одна копия кода... как-нибудь на досуге проверю...

небольшой досуг наступил несколько минут назад: действительно, все продумано за нас - в конце концов остается только одна копия кода даже при включении в h-файл
так что теперь я смело могу объявить способ (1) - безграмотным и советовать ним не пользоваться smile


--------------------
qqq
PM WWW   Вверх
Dark Elf
Дата 31.1.2005, 22:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 576
Регистрация: 26.12.2003
Где: Брисбен

Репутация: нет
Всего: 10



Большое спасибо всем ответившим, особенно maxim1000


--------------------
PM MAIL WWW ICQ Skype GTalk Jabber MSN   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Visual C++/MFC/WTL | Следующая тема »


 




[ Время генерации скрипта: 0.0491 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.