Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 12, средняя оценка - 4.83
Chelioss
181 / 181 / 21
Регистрация: 08.01.2011
Сообщений: 1,139
#1

Как влияет inline и обертка(#ifndef #define #endif) .h файла на компоновщик. - C++

08.01.2012, 18:50. Просмотров 1545. Ответов 8
Метки нет (Все метки)

Есть файл Point.h:
Point.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#ifndef POINT_GUARD
#define POINT_GUARD
 
//--------------------------------------------------------------------------------------------
 
class Point
{
public:
    unsigned int x,y;
    Point( const int m_x, const int m_y ): x( m_x ), y( m_y ) {}
    Point(): x(0), y(0) {}
};
 
bool operator == ( const Point &left, const Point &right )
{
    return ( left.x == right.x ) && ( left.y == right.y );
}
bool operator != ( const Point &left, const Point &right )
{
    return !( left == right );
}
 
//--------------------------------------------------------------------------------------------
 
#endif // POINT_GUARD

Напишу куда подключается файл Point.h.
Point.h подключается в Graph.h и MyWindow.h. В GUI.h подключаются файлы Graph.h и MyWindow.h.
В Main.cpp подключаются GUI.h и Graph.h
В MyWindow.cpp подключаются MyWindow.h и Graph.h и GUI.h.
При компоновке появляется такая ошибка:
Ошибки
1>MyWindow.obj : error LNK2005: "bool __cdecl operator==(class Point const &,class Point const &)" (??8@YA_NABVPoint@@0@Z) уже определен в Main.obj
1>MyWindow.obj : error LNK2005: "bool __cdecl operator!=(class Point const &,class Point const &)" (??9@YA_NABVPoint@@0@Z) уже определен в Main.obj

Причем на Main.obj компоновщик не ругается, хотя там тоже подключается косвенно Point.h.
Почему обертка(защита) не срабатывает я не понимаю.

Если добавить в файл Point.h перед двумя перегрузками операторов == и != спецификатор inline, то ошибка пропадает. Почему?
inline это инструкция для препроцессора как #define #endif и т.д.?

Point.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#ifndef POINT_GUARD
#define POINT_GUARD
 
//--------------------------------------------------------------------------------------------
 
class Point
{
public:
    unsigned int x,y;
    Point( const int m_x, const int m_y ): x( m_x ), y( m_y ) {}
    Point(): x(0), y(0) {}
};
 
inline bool operator == ( const Point &left, const Point &right )
{
    return ( left.x == right.x ) && ( left.y == right.y );
}
inline bool operator != ( const Point &left, const Point &right )
{
    return !( left == right );
}
 
//--------------------------------------------------------------------------------------------
 
#endif // POINT_GUARD

http://www.cyberforum.ru/cpp-beginners/thread1555083.html
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
08.01.2012, 18:50
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Как влияет inline и обертка(#ifndef #define #endif) .h файла на компоновщик. (C++):

Объясните, в чем суть директив #ifndef/#define/#endif
Не понял в чем суть директив: #ifndef .. #define.. #endifОбъясните...

Нюансы синтаксиса: #pragma once и ifndef define endif это одно и тоже?
Я недопонял #pragma once и ifndef define endif это одной и тоже?

Команды #ifndef #ifdef и #endif
Помогите разобраться с командами #ifndef #endif и #ifndef в книге все как то не...

#define VS inline
Что работает быстрее: #define SQR(x) x*x void Func() { for(int i = 0; i...

inline и define
Почему использовать inline-функции лучше, чем использовать команду...

8
NoMasters
Псевдослучайный
1909 / 1120 / 90
Регистрация: 13.09.2011
Сообщений: 3,178
08.01.2012, 18:59 #2
Принципиального отличия между .h и .cpp файлами нет, компилируется в итоге один файл, содержащий текст всех включений. Поэтому у вас во всех объектных файлах действительно присутствует по реализации этих функций. А инлайн функции как таковые отсутствуют в итоговых файлах, их тело просто замещает вызовы.
А макрообертки используются для избежания повторных включений внутри одного компилируемого файла.
1
Chelioss
181 / 181 / 21
Регистрация: 08.01.2011
Сообщений: 1,139
08.01.2012, 19:11  [ТС] #3
NoMasters
Из вашего сообщения не понятно почему обертка(защита) не помогла.
Вот эксперимент, в котором обертка(защита) помогла:
код
Файл Point.h:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#ifndef POINT_GUARD
#define POINT_GUARD
 
struct Point
{
    unsigned int x, y;
    Point() : x(0), y(0) {}
};
 
bool operator == ( const Point &left, const Point &right )
{
    return ( left.x == right.x ) && ( left.y == right.y );
}
 
bool operator != ( const Point &left, const Point &right )
{
    return !( left == right );
}
 
#endif
Файл main.cpp:
C++
1
2
3
4
5
#include "Point.h"
#include "Point.h"
int main()
{
}


Добавлено через 5 минут
Я думаю тут надо понять как работает обертка(защита) и тогда появится ответ на мой вопрос.
0
NoMasters
Псевдослучайный
1909 / 1120 / 90
Регистрация: 13.09.2011
Сообщений: 3,178
08.01.2012, 19:18 #4
Не помогла потому, что собиралось несколько отдельных объектных файлов. В каждом действительно могло оказаться не более одной реализации, но от этого при линковке лучше не станет.
Обертка работает очень просто: если макрос уже определён, код повторно не включается.
1
Chelioss
181 / 181 / 21
Регистрация: 08.01.2011
Сообщений: 1,139
08.01.2012, 19:41  [ТС] #5
Цитата Сообщение от NoMasters Посмотреть сообщение
макрос уже определён
Определение макроса действует на весь проект или только на один файл?
0
NoMasters
Псевдослучайный
1909 / 1120 / 90
Регистрация: 13.09.2011
Сообщений: 3,178
08.01.2012, 19:44 #6
Отдельно на каждый файл, скармливаемый компилятору.
1
Chelioss
181 / 181 / 21
Регистрация: 08.01.2011
Сообщений: 1,139
08.01.2012, 20:26  [ТС] #7
В общем, непонято откуда ошибка взялась.
0
NoMasters
Псевдослучайный
1909 / 1120 / 90
Регистрация: 13.09.2011
Сообщений: 3,178
08.01.2012, 20:36 #8
Оттуда, что компилируемых файлов в проекте было больше одного.
1
Evg
Эксперт CАвтор FAQ
18938 / 6899 / 513
Регистрация: 30.03.2009
Сообщений: 19,437
Записей в блоге: 30
09.01.2012, 12:36 #9
Цитата Сообщение от Chelioss Посмотреть сообщение
В общем, непонято откуда ошибка взялась
Всё понятно. В заголовочные файлы можно складывать только то, что разрешено включать сразу в несколько файлов: описания типов, описания макросов, описание функций и методов, для которых допустимы множественные определения (в случае Си++ это функции и методы с модификатором inline).

Ты же в своём коде впендюрил туда оператор (функцию). Если бы оператор был описан внутри класса, то он бы имел неявный модификатор inline и всё было бы хорошо. Но он описан вне класса, а потому в каждом файле, в котором делается подключение твоего Point.h, образуется одна копия оператора, что и влечёт за собой множественное определение на линковке.

В проекте, состоящем из нескольких файлов *.cpp, каждый файл *.cpp компилируется отдельным запуском компилятора независимо от остальных файлов *.cpp. А guard, кстати, используется не для этих целей

Добавлено через 1 минуту
Цитата Сообщение от Evg Посмотреть сообщение
Если бы оператор был описан внутри класса, то он бы имел неявный модификатор inline и всё было бы хорошо
Оператор не является членом класса, это я проглядел. Поэтому правильным было бы сказать, что "если бы оператор был описан с модификатором inline"
1
09.01.2012, 12:36
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
09.01.2012, 12:36
Привет! Вот еще темы с решениями:

Ifndef-define-endif
Qt Creator по умолчанию создаёт хэдер любого класса с подобной шапкой: ...

#ifndef #endif и extern
#ifndef #endif и extern Как применять эти директивы и зачем они? без...

Странное предупреждение при использовании #ifndef-#endif
Создаю заголовочный файл: #ifndef EXAMPLE_H #define EXAMPLE_H bool...

Вопрос по Си: #ifndef ... #define (продолжено)
Пишу сюда, потому что здесь много народу толчется, хотя столкнулся с...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru