Russian Qt Forum

Программирование => С/C++ => Тема начата: serg_hd от Февраль 24, 2011, 20:17



Название: Multiple definition of function
Отправлено: serg_hd от Февраль 24, 2011, 20:17
Здравствуйте, вопрос, возможно, покажется нубским, но всё же рискну. Есть у меня в проекте один файлик, defines.h, в котором я декларирую и тут же инициализирую различные нужности, например енумы, структуры, классы, typedef'ы, define'ы, etc. И подключаю этот хидер для нужного мне класса когда надо (т.е. подключается он во всём проекте не единожды). Но решил в defines.h также добавить:
Код
C++ (Qt)
namespace MySpace
{
QString getStr()
{
 QString str;
 //...  
 return str;
}
}
 

Препроцессинг нормально, компиляция нормально, но линковщик стал неравнодушен:

.../defines.h:188: multiple definition of `MySpace::getStr()'

Так вот, собственно, и вопрос: почему? Ведь выше от неё описаны классы со своими методами (именно инициализированы, как и эта функция) и куча других данных, а не нравится именно эта функция. Хорошо, разделил на .h и .cpp. Теперь в defines.h только декларация этой функции (а всё что выше не трогал, то есть там присутствуют и инициализации в отличие от этой функции):

Код
C++ (Qt)
namespace MySpace
{
QString getStr();
}
 

Ну а в defines.cpp инициализировал функцию как обычно. Всё заработало. Так вот, нельзя ли обойтись только .h-файлом? И вообще, может быть есть какие-то негласные стандарты для осуществления подобного подхода? Просто мне показался вариант использования функции MySpace::getStr() как наиболее удобным, а использовать её как статическую - банально.



Название: Re: Multiple definition of function
Отправлено: Blackwanderer от Февраль 24, 2011, 20:21
А защита от множественного включения в вашем *.h файле есть?


Название: Re: Multiple definition of function
Отправлено: serg_hd от Февраль 24, 2011, 20:21
А защита от множественного включения в вашем *.h файле есть?
Конечно, стражи на месте. Т.е. в одном классе (у меня для каждого класса свои, отдельные пары .h/.cpp) 2х и более подключений defines.h быть не может.


Название: Re: Multiple definition of function
Отправлено: serg_hd от Февраль 24, 2011, 20:23
Я так понимаю, что если проинициализирован не тип (класс, структура и т.п.), а функция, как в моём случае, то линковщик её воспринимает глобально. Т.е. каждый раз, когда есть инклуд defines.h в какой-либо файл выдаёт что функция уже существует.


Название: Re: Multiple definition of function
Отправлено: Igors от Февраль 24, 2011, 20:43
Ну а в defines.cpp инициализировал функцию как обычно. Всё заработало. Так вот, нельзя ли обойтись только .h-файлом?
Если хотите тело ф-ции в h файле - объявляйте ее как inline. Если связались с template - все тела должны быть в h файлах

Я так понимаю, что если проинициализирован не тип (класс, структура и т.п.), а функция, как в моём случае, то линковщик её воспринимает глобально. Т.е. каждый раз, когда есть инклуд defines.h в какой-либо файл выдаёт что функция уже существует.
Да, т.к. эта ф-ция будет в каждом cpp который включает этот h


Название: Re: Multiple definition of function
Отправлено: serg_hd от Февраль 24, 2011, 20:52
Если хотите тело ф-ции в h файле - объявляйте ее как inline. Если связались с template - все тела должны быть в h файлах
Совет с inline помог, спасибо (не знал, что он влияет также на "глобальность" функции). Но с шаблонами позволю себе не согласиться, их можно резделить, специально пробовал. Только при разделении в .cpp нужно описывать каждый тип с которым будет работать шаблон, а это дополнительно столько строк, сколько будет типов, принимаемых шаблоном, что не есть хорошо. Просто хотел сказать, что на самом деле не "должны", а "настоятельно рекомендуется" :)


Название: Re: Multiple definition of function
Отправлено: lit-uriy от Февраль 24, 2011, 21:24
>>Я так понимаю, что если проинициализирован не тип (класс, структура и т.п.), а функция,
что понимается под инициализацией функции?


Название: Re: Multiple definition of function
Отправлено: serg_hd от Февраль 24, 2011, 21:27
>>Я так понимаю, что если проинициализирован не тип (класс, структура и т.п.), а функция,
что понимается под инициализацией функции?
описание её тела


Название: Re: Multiple definition of function
Отправлено: Igors от Февраль 24, 2011, 21:47
Но с шаблонами позволю себе не согласиться, их можно резделить, специально пробовал. Только при разделении в декларации нужно описывать каждый тип с которым будет работать шаблон, а это дополнительно столько строк, сколько будет типов, принимаемых шаблоном, что не есть хорошо. Просто хотел сказать, что на самом деле не "должны", а "настоятельно рекомендуется" :)
"Должны" - иначе Вы сможете вызывать template ф-ции только из того cpp файла где их тела (но не из другого). Если template класс имеет static члены, они также должны быть в h файле (и их сынтаксыс с непривычки бьет по ушам  :))


Название: Re: Multiple definition of function
Отправлено: serg_hd от Февраль 24, 2011, 21:51
Но с шаблонами позволю себе не согласиться, их можно резделить, специально пробовал. Только при разделении в декларации нужно описывать каждый тип с которым будет работать шаблон, а это дополнительно столько строк, сколько будет типов, принимаемых шаблоном, что не есть хорошо. Просто хотел сказать, что на самом деле не "должны", а "настоятельно рекомендуется" :)
"Должны" - иначе Вы сможете вызывать template ф-ции только из того cpp файла где их тела (но не из другого). Если template класс имеет static члены, они также должны быть в h файле (и их сынтаксыс с непривычки бьет по ушам  :))
а, речь идёт о шаблонных функциях. Я думал о классах, содержащих шаблонные методы.


Название: Re: Multiple definition of function
Отправлено: Igors от Февраль 24, 2011, 21:55
а, речь идёт о шаблонных функциях. Я думал о классах, содержащих шаблонные методы.
Без разницы, template ф-ция - член или просто ф-ция. Должны быть "в одной единице компиляции"


Название: Re: Multiple definition of function
Отправлено: serg_hd от Февраль 24, 2011, 22:04
а, речь идёт о шаблонных функциях. Я думал о классах, содержащих шаблонные методы.
Без разницы, template ф-ция - член или просто ф-ция. Должны быть "в одной единице компиляции"

Класс разделяется без проблем:
SomeClass.h
Код
C++ (Qt)
class SomeClass
{
 public:
 template<class T> void Fun(T* pT);
};
 

SomeClass.cpp
Код
C++ (Qt)
template void SomeClass::Fun<int>(int*); //тип 1
template void SomeClass::Fun<double>(double*);//тип 2
template<class T> void SomeClass::Fun(T* pT)
{
 //...
}
 


Название: Re: Multiple definition of function
Отправлено: Igors от Февраль 24, 2011, 23:00
Класс разделяется без проблем:
Попробуйте вызвать Fun() из др. cpp (а не из SomeClass.cpp). Линкеру это не понравится..


Название: Re: Multiple definition of function
Отправлено: serg_hd от Февраль 25, 2011, 00:26
Попробуйте вызвать Fun() из др. cpp (а не из SomeClass.cpp). Линкеру это не понравится..
Так ведь в SomeClass.cpp я его и не вызываю. Я его там инициализирую (описываю) и декларирую другие типы, которые будет использовать шаблон, как я уже выше упоминал.

По сабжу:
SomeClass.h
Код
C++ (Qt)
#ifndef SOMECLASS_H
#define SOMECLASS_H
 
class SomeClass
{
public:
 template<class T> void Fun(T pT);
};
 
#endif
 

SomeClass.cpp
Код
C++ (Qt)
#include <iostream>
#include "SomeClass.h"
 
template void SomeClass::Fun<int>(int); //тип 1
template void SomeClass::Fun<double>(double);//тип 2
template<class T> void SomeClass::Fun(T pT)
{
std::cout << pT << std::flush;
}
 

MyClass1.h
Код
C++ (Qt)
#ifndef MYCLASS1_H
#define MYCLASS1_H
 
class SomeClass;
 
class MyClass1
{
public:
MyClass1();
SomeClass* t_member;
};
 
#endif
 

MyClass1.cpp
Код
C++ (Qt)
#include "MyClass1.h"
#include "SomeClass.h"
 
MyClass1::MyClass1(): t_member(new SomeClass) { }
 

main.cpp
Код
C++ (Qt)
#include "MyClass1.h"
#include "SomeClass.h"
 
int main()
{
MyClass1 class1;
class1.t_member->Fun<int>(111);
}
 

Никаких проблем!


Название: Re: Multiple definition of function
Отправлено: Fat-Zer от Февраль 25, 2011, 05:26
интересный способ заставить шаблон работать только с конкретными типами.

Ещё стандарт говорит о мистическом ключевом слове export, правда я не видел компилятор, который его поддерживает...