реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> шаблоны С++, возникла проблема...
Legotron
сообщение Apr 28 2007, 13:36
Сообщение #1


инопланетянин
***

Группа: Свой
Сообщений: 236
Регистрация: 24-12-06
Из: Питер
Пользователь №: 23 832



Добрый день!

Помогите разобраться в чем ошибка?
Код следующий...

Код
template <class T>
class A {

public:

void Func();

};

template <class T>
void A<T>::Func()
{
}

void TestTemplate(void)
{
A<int> AObj;        // Создаем объект тип А для int
AObj.Func();        // Эта строка приводит к ошибке линкера  (исправил было A вместо AObj) :)
}


Этот код компилирутся без ошибок.
Ошибка возникает на этапе ликовки...

Код
*** ERROR L127: UNRESOLVED EXTERNAL SYMBOL
    SYMBOL:  Func__12SAS__tm__2_cFv_v
    MODULE:  EMF.obj (EMF)
*** ERROR L128: REFERENCE MADE TO UNRESOLVED EXTERNAL
    SYMBOL:  Func__12SAS__tm__2_cFv_v
    MODULE:  EMF.obj (EMF)
    ADDRESS: 16E8H
Target not created


Какие есть соображения по этому поводу?

Сообщение отредактировал Legotron - Apr 28 2007, 14:05
Go to the top of the page
 
+Quote Post
DiMomite
сообщение Apr 28 2007, 13:57
Сообщение #2


Участник
*

Группа: Свой
Сообщений: 47
Регистрация: 8-04-06
Из: Одесса
Пользователь №: 15 959



Цитата
A.Func();           // Эта строка приводит к ошибке линкера


Заменить на
AObj.Func();
попробуй, или я чего-то не понял?
Потому что Builder у меня ругнулся на этапе компиляции:
[C++ Error] Unit1.cpp(32): E2102 Cannot use template 'A<T>' without specifying specialization parameters

Сообщение отредактировал DiMomite - Apr 28 2007, 13:59
Go to the top of the page
 
+Quote Post
forever failure
сообщение Apr 28 2007, 13:57
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 256
Регистрация: 6-03-05
Из: Екатеринбург
Пользователь №: 3 112



void TestTemplate(void)
{
A<int> AObj; // Создаем объект тип А для int
A.Func(); // Эта строка приводит к ошибке линкера
/* оно и неправильно. может имелось ввиду:*/
AObj.Func (); // ы ?
}
Go to the top of the page
 
+Quote Post
Legotron
сообщение Apr 28 2007, 14:03
Сообщение #4


инопланетянин
***

Группа: Свой
Сообщений: 236
Регистрация: 24-12-06
Из: Питер
Пользователь №: 23 832



Цитата(forever failure @ Apr 28 2007, 14:57) *
void TestTemplate(void)
{
A<int> AObj; // Создаем объект тип А для int
A.Func(); // Эта строка приводит к ошибке линкера
/* оно и неправильно. может имелось ввиду:*/
AObj.Func (); // ы ?
}

Да правильно, имелось ввиду АObj! smile.gif
Но ошибка не в этом!
Это я накосячил во время составления поста.
В проекте у меня совсем все подругому названо...
Я для простоты переделал в А, B, C.
Go to the top of the page
 
+Quote Post
forever failure
сообщение Apr 28 2007, 16:46
Сообщение #5


Местный
***

Группа: Участник
Сообщений: 256
Регистрация: 6-03-05
Из: Екатеринбург
Пользователь №: 3 112



Дык проблема есть или исчерпана ?
Если есть - извольте полный пробленмый код изобразить (лучше тупым копи - пастом, дабы не внести ошибок) и ключи компиляции. И, кстати, указать какой компилятор/хост/таргет.

И, ещё. Объявление
template <class T>
class A {
public:
void Func();
};
и определение
template <class T>
void A<T>::Func()
{
}
находятся в одной единице трансляции или в разных ?
Go to the top of the page
 
+Quote Post
Legotron
сообщение Apr 28 2007, 22:22
Сообщение #6


инопланетянин
***

Группа: Свой
Сообщений: 236
Регистрация: 24-12-06
Из: Питер
Пользователь №: 23 832



Цитата(forever failure @ Apr 28 2007, 17:46) *
Дык проблема есть или исчерпана ?

Проблема есть. sad.gif

Теперь по порядку:

IDE/компилятор: Keil 166 EC++.
Проц Infineon XC167.

List.h...
Код
template <class T>
class TList {


struct _SList {

    T * item;
    struct _SList * next;
    struct _SList * prev;

};

    typedef struct _SList SList;

public:

    SList * base;
    SList * NewItem;
    
    TList(void) {base = NULL; NewItem = NULL;};
    void AddItem(T * PRec);
    U16 CountItems(void);

};

List.cpp...
Код
#include <stdio.h>                /* standard I/O .h-file              */

#include <stdlib.h>
#include <intrins.h>
#include <absacc.h>            // Absolute Memory Access
#include "main.h"
#include "gl.h"
#include "ec_error.h"
#include "Graph.h"
#include "List.h"

//------------------------------------------------------------------------------

template <class T>
void TList<T>::AddItem(T * PRec)
{
SList * Current;

if(base != NULL)
{
    Current = base;
    while(Current->next != NULL)
        Current = Current->next;

    NewItem = new SList;
    Current->next = NewItem;
    NewItem->next = NULL;
    NewItem->prev = Current;
    NewItem->item = PRec;
}
else
{
    base = new SList;
    base->next = NULL;
    base->prev = NULL;
    base->item = PRec;    
}

}

//------------------------------------------------------------------------------

template <class T>
U16 TList<T>::CountItems(void)
{
U16 i = 0;
SList * Current;

if(base != NULL)
{
    Current = base;
    while(Current->next != NULL)
    {
        Current = Current->next;
        i++;
    }
}
return i;
}
//------------------------------------------------------------------------------

Test.cpp...
Код
void Test(void)
{
U16 cnt;

TList<U16> A;
cnt  = A.CountItems();  // Без этой строчки никаких ошибок вообще нет!
}


P.S. Если ф-ции члены класса делать inline внутри класса - ошибок тоже нет
Вот, если не затруднит гляньте плз smile.gif
Go to the top of the page
 
+Quote Post
forever failure
сообщение Apr 29 2007, 06:45
Сообщение #7


Местный
***

Группа: Участник
Сообщений: 256
Регистрация: 6-03-05
Из: Екатеринбург
Пользователь №: 3 112



Самое простое и правильное в этом случае решение - перенести весь код, функций-членов шаблона класса из .cpp в заголовочный файл .h.

Более подробно почему и отчего так можно узнать например здесь
Go to the top of the page
 
+Quote Post
Legotron
сообщение Apr 29 2007, 16:04
Сообщение #8


инопланетянин
***

Группа: Свой
Сообщений: 236
Регистрация: 24-12-06
Из: Питер
Пользователь №: 23 832



Большое спасибо за помощь! smile.gif
Сейчас проверить к сож. не могу. sad.gif После праздников попробую сделать как вы сказали.

P.S.
Цитата(forever failure @ Apr 29 2007, 07:45) *
Самое простое и правильное в этом случае решение - перенести весь код, функций-членов шаблона класса из .cpp в заголовочный файл .h.

При этом ф-ции описывать внутри класса? или просто в 1 модуле *.h?

Если внутри класса, то это неудобно.
Если в 1 модуле, тогда почему у меня не проходила ошибка, когда я описание класса помещал в .Cpp файл, где и ф-ции?
Go to the top of the page
 
+Quote Post
forever failure
сообщение Apr 29 2007, 19:24
Сообщение #9


Местный
***

Группа: Участник
Сообщений: 256
Регистрация: 6-03-05
Из: Екатеринбург
Пользователь №: 3 112



Функции можно описывать где угодно, главное, чтобы в точке инстанцирования шаблона было видимо и описание прототипа шаблонной функции и определение её тела. Т. е. это дело можно расположить в заголовке, но определения вынести вне класса, а в классе поместить только объявления. А чтобы было возможно размещать определения шаблонов в отдельной единице трансляции (т. е. в другом файле .cpp), компилятор должен поддерживать ключевое слово export (или ещё называется это средство - exported templates) - возможность, определённую стандартом языка, но почти никем не поддерживаемую.

В общем см. ссылку выше.
Go to the top of the page
 
+Quote Post
Legotron
сообщение May 3 2007, 12:27
Сообщение #10


инопланетянин
***

Группа: Свой
Сообщений: 236
Регистрация: 24-12-06
Из: Питер
Пользователь №: 23 832



Что не совсем у меня выходит! sad.gif

В принципе работает. smile.gif Но только если тела ф-ций членов класса находятся внутри класса.

В случае "#include "file.cpp" /* брррр...... ахтунг, но работать будет*/" у меня действительно ахтунг.
Причем пример из статьи работает. А моя программа нет.

В примере в файле file.cpp
ф-ция с пустым телом

template <class T> C<T> :: C (void): t (1) {;}

В чем может быть дело?

Сообщение отредактировал Legotron - May 3 2007, 12:29
Go to the top of the page
 
+Quote Post
dxp
сообщение May 3 2007, 16:10
Сообщение #11


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



Цитата(Legotron @ May 3 2007, 16:27) *
Что не совсем у меня выходит! sad.gif

В принципе работает. smile.gif Но только если тела ф-ций членов класса находятся внутри класса.

В случае "#include "file.cpp" /* брррр...... ахтунг, но работать будет*/" у меня действительно ахтунг.
Причем пример из статьи работает. А моя программа нет.

В примере в файле file.cpp
ф-ция с пустым телом

template <class T> C<T> :: C (void): t (1) {;}

В чем может быть дело?

Не понятно. Вы определения функций-членов шаблона вынесли в заголовок? Т.е. все определение шаблона - и сам шаблон-класс, и все его внешние определения (функции-члены) должны быть определены в заголовочном файле. Который уже включается. А в исходном файле только использование.


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 30th July 2025 - 19:12
Рейтинг@Mail.ru


Страница сгенерированна за 0.01441 секунд с 7
ELECTRONIX ©2004-2016