Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Глобальная функция, как объявить чтоб везде... 
:(
    Опции темы
Гость05
Дата 17.8.2005, 10:15 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Привет, Alll!

как объявить функцию которая была бы видна из любой части проекта состоящего из нескольких классов => несколько хэдеров и сипипишников, каковы ньюансы подобного объявления?

Спасибо.
  Вверх
Denn
Дата 17.8.2005, 11:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



В одном из хедеров делаешь предварительное объявление:
void func();
В cpp ее описываешь
void func()
{
}
хедер добавляешь где надо вызывать функцию.

PM MAIL ICQ   Вверх
mr.Anderson
Дата 18.8.2005, 18:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


iOS Lead Developer
****


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

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



Ага. К примеру:
Код

//Это пишем заголовочный файл (хедер)
void YOUR_FUNC(it_arguments);
//Дальше еще прототипы других функций, если надо
//Затем пишем саму функцию:
void YOUR_FUNC(int arg1,char arg2)
{
//Тут пишем тело функции
}

Все. Хедер готов. Теперь в основной программе:
Код

//Это - основная программа

#include <имя_хедера.h>
void main()
{
//Тело главной функции
...
//Затем вызов встроенной в хедер функции:
YOUR_FUNC(23,'a');
}

Ну как, помогло? smile


--------------------
user posted image

user posted image
PM MAIL ICQ Skype   Вверх
Hroft
Дата 19.8.2005, 11:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



sim7
Ага, а теперь воткни свой хеадер не в один файлик, а, например, в два. И любуйся. Для КЛАССОВ эквивалентные определения допускаются, а вот функций у тебя получится две в объектниках разных. Именно для того хеадеры и предназначены, чтобы отделять объявление и определение.
PM MAIL ICQ   Вверх
Denn
Дата 19.8.2005, 12:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Hroft
а какие объектики ты имеешь в виду?
PM MAIL ICQ   Вверх
Hroft
Дата 19.8.2005, 13:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(Hroft @ 19.8.2005, 11:16)
объектниках

Это файлы, сгенерированные компилятором после обработки единицы компиляции. Короче, то, что получается из .CPP и отдается линкеру.
PM MAIL ICQ   Вверх
Denn
Дата 19.8.2005, 14:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



поставь #pragma once и будет одна единица компиляции и одна функция.
PM MAIL ICQ   Вверх
Hroft
Дата 19.8.2005, 15:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Ни разу ей не пользовался, но...
Если написать в его хеадере прагму, что, кстати, не сделано, то второй раз хеадер просто не включится, если он уже включен, ведь так? Если так, то ошибка не в этом, этой тут и быть не может...
PM MAIL ICQ   Вверх
mr.Anderson
Дата 19.8.2005, 16:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


iOS Lead Developer
****


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

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



Вообще, я чаще вот так делаю (кстати, скажите, правильно или нет):
Код

#ifndef my_header.h
#include <my_header.h>
#endif

Я не имел возможности проверить, так ли.


--------------------
user posted image

user posted image
PM MAIL ICQ Skype   Вверх
Selecter
Дата 19.8.2005, 17:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(sim7 @ 19.8.2005, 16:05)
Вообще, я чаще вот так делаю (кстати, скажите, правильно или нет):
Код

#ifndef my_header.h
#include <my_header.h>
#endif

Я не имел возможности проверить, так ли.

По-моему, вот так:
Код

#ifndef MY_HEADER_H
#include <my_header.h>
#define MY_HEADER_H
#endif

PM MAIL   Вверх
mr.Anderson
Дата 19.8.2005, 18:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


iOS Lead Developer
****


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

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



А зачем define? Куда мне константа?


--------------------
user posted image

user posted image
PM MAIL ICQ Skype   Вверх
Mayk
Дата 19.8.2005, 18:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


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

Репутация: 45
Всего: 134



По хорошему это делается так
blahblah.h:
Код

#ifndef __blahblah_h
#define __blahblah_h
class Blahblah
{
   blah blahblah();
   blah blahblah(blah bla);
};
#endif





--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
mr.Anderson
Дата 19.8.2005, 18:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


iOS Lead Developer
****


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

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



Ух ты! Обалдеть! А пояснить можете?
1) Почему #define, а не #include?
2) Почему все помещено в #ifndef и #endif? Почему нельзя писать код хедера после #endif?
3) Где объявление класса - это тело хедера, так?


--------------------
user posted image

user posted image
PM MAIL ICQ Skype   Вверх
Mayk
Дата 19.8.2005, 19:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


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

Репутация: 45
Всего: 134



Цитата(sim7 @ 19.8.2005, 22:26)
3) Где объявление класса - это тело хедера, так?

да
Цитата(sim7 @ 19.8.2005, 22:26)
Почему #define, а не #include?

Потому что они служат для абсолютно разных целях - первый определяет макрос, за место второго встает тело указанного файла.

Цитата(sim7 @ 19.8.2005, 22:26)
Почему все помещено в #ifndef и #endif? Почему нельзя писать код хедера после #endif?

Потому что иначе они могут продублироваться, если ты заинклюдишь файл дважды. Компилятору это может не понравится.
Увидев директиву #ifndef aaa, препроцессор проверит был ли установлен макрос aaa. Все остальное вплоть до #endif(или #else) будет отдано на съедение компилятору только в том случае, если он установлен не был. А в первом случае это так.
Следующая строка определяет этот самый макрос. #endif означает конец ветвления.
Далее файл подключается второй раз - увидев директиву #ifndef aaa, препроцессор проверит был ли установлен макрос aaa.
Он уже был установлен, так что препроцессор пропустит всё до конца файла. Компилятор не получит двойного определения класса, все будут счастливы. Заместо #ifndef/#define/#endif можно использовать мелкософтофский #pragma once - в этом случае хедер будет обработан лишь один раз на компиляцию независимо от чего либо.

Но это не решит проблемы, которую описал Hroft. Если ты объявишь ф-цию в хедере, который подключается из 1.cpp и 2.cpp, то ф-ция будет лежать в обоих объектных файлах - как в 1.obj, так и в 2.obj, так как компилирование 1.cpp НИКАК не связано с компилированием 2.cpp.Поэтому компилятор откомпилирует функцию дважды, ошибок не будет. Но вот на стадии линкования...
Линкер видит, что в 1.obj есть ф-ция YOUR_FUNC и в 2.obj есть ф-ция с имененм YOUR_FUNC. Да к тому же они принимают одинаковые параметры, что совсем не допустимо. Если компоновщик увидит, что кто-то вызывает YOUR_FUNC, он не сможет определить какую именно YOUR_FUNC вызывают - из файла 1.obj, или из файла 2.obj. Поэтому он будет ругаться.



--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
mr.Anderson
Дата 19.8.2005, 21:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


iOS Lead Developer
****


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

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



Так я запутался - что использовать: #include или #define?
А символы подчеркивания нужны перед именами файлов, как в вашем коде?
А про повторы функций - а нельзя создать в хедере две функции с разными именами? И вызывать по разным именам?


--------------------
user posted image

user posted image
PM MAIL ICQ Skype   Вверх
Mayk
Дата 20.8.2005, 05:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


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

Репутация: 45
Всего: 134



Цитата(sim7 @ 20.8.2005, 01:51)
#include или #define?

Инклюд в .cpp, define в .h
Цитата(sim7 @ 20.8.2005, 01:51)
А символы подчеркивания нужны перед именами файлов, как в вашем коде?

По желанию, но лучше использовать чтоб потом не думать, почему компилятор не видит идентификатор "aaa", который был заменен препроцессором на "".
Цитата(sim7 @ 20.8.2005, 01:51)
нельзя создать в хедере две функции с разными именами? И вызывать по разным именам?

Нет, если только функции не объявлены как inline или static.


--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
Denn
Дата 21.8.2005, 08:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Mayk

Цитата(Mayk @ 19.8.2005, 19:12)
Но это не решит проблемы, которую описал Hroft. Если ты объявишь ф-цию в хедере, который подключается из 1.cpp и 2.cpp, то ф-ция будет лежать в обоих объектных файлах - как в 1.obj, так и в 2.obj, так как компилирование 1.cpp НИКАК не связано с компилированием 2.cpp.Поэтому компилятор откомпилирует функцию дважды, ошибок не будет. Но вот на стадии линкования...
Линкер видит, что в 1.obj есть ф-ция YOUR_FUNC и в 2.obj есть ф-ция с имененм YOUR_FUNC. Да к тому же они принимают одинаковые параметры, что совсем не допустимо. Если компоновщик увидит, что кто-то вызывает YOUR_FUNC, он не сможет определить какую именно YOUR_FUNC вызывают - из файла 1.obj, или из файла 2.obj. Поэтому он будет ругаться.


Я написал следующий код (компилятор vc):

a.h:
Код

#pragma once


b.h:
Код

#pragma once

void func();


a.cpp:
Код

#include "stdafx.h"

#include "b.h"


b.cpp:
Код

#include "stdafx.h"

#include "b.h"

void func()
{
}


Как видно, файл, содержащий объявление func() включается дважды. Однако все компилится и компонуется нормально. Причем при просмотре объектных файлов func() обнаруживается только в b.obj. Это происходит потому, что компилятор работает не с файлом исходного кода как такогого, а с единицей трансляции, которая получается после обработки кода препроцессором.

PM MAIL ICQ   Вверх
Mayk
Дата 21.8.2005, 09:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


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

Репутация: 45
Всего: 134



Цитата(Denn @ 21.8.2005, 12:22)
содержащий объявление func()

#pragma once тут не при чём. Ты можешь в хедере(да где угодно) сотню раз объявить void func(), и всё будет компилироваться нормально. Попробуй откомпилировать вот это:
Код

int a();int a();int a();int a();int a();int a();int a();int a();int a();int a();int a();int a();int a();int a();

int a(){return 0;}
int main(){return a();}

Сколько ошибок в этом коде?
Как бы там ни было, напомню код с которого всё началось:
Цитата(sim7 @ 18.8.2005, 22:53)
//Это пишем заголовочный файл (хедер)
void YOUR_FUNC(it_arguments);
//Дальше еще прототипы других функций, если надо
//Затем пишем саму функцию:
void YOUR_FUNC(int arg1,char arg2)
{
//Тут пишем тело функции
}

Цитата(sim7 @ 18.8.2005, 22:53)
Все. Хедер готов.

В хедере нельзя описывать тело ф-ции, если только ф-ция не объявлена как inline, или static(static ф-ция в хедере - это довольно оригинально smile).

Цитата(Denn @ 21.8.2005, 12:22)
Как видно, файл, содержащий объявление func() включается дважды.

Не совсем верно. Она включается один раз на каждый .cpp файл. Мы не имеем право говорить "включается дважды" для независимых друг от друга процессов(а компиляция a.cpp, повторюсь, НИКАК не зависит от компиляции b.cpp. Ну вообще никак. Если только по мазохистким соображениям не делать #include "a.cpp").
Это сродни тому, что сказать, что у двух людей одно сердце: как каждый человек получает собственное сердце при рождении, так и при компилирования каждый .cpp файл получает свою копию заголовка. При компиляции b.cpp компилятор НЕ БУДЕТ знать, что заголовок func.h уже включался в a.cpp. Откуда ему это знать, собственно говоря? Неоткуда. Да и зачем ему это знать?


--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
mr.Anderson
Дата 21.8.2005, 10:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


iOS Lead Developer
****


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

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



Цитата
В хедере нельзя описывать тело ф-ции, если только ф-ция не объявлена как inline, или static

Что-что?! А я описал в своем хедере много прототипов и самих функций, подключаю его - и все нормально работает.
А если нельзя в хедере, то где же тогда? А прототипы куда пхать?


--------------------
user posted image

user posted image
PM MAIL ICQ Skype   Вверх
Artiom
Дата 21.8.2005, 11:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(sim7 @ 21.8.2005, 09:32)
А если нельзя в хедере, то где же тогда?

Реализацию функции можно описать где угодно.


--------------------
Если тебя жизнь трахает, значит, ты ещё живой
PM MAIL ICQ   Вверх
Mayk
Дата 21.8.2005, 11:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


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

Репутация: 45
Всего: 134



Цитата(Artiom @ 21.8.2005, 15:20)
Реализацию функции можно описать где угодно.

Только хедер - не самое подходящее место для этого:

a.cpp:
Код

#include "a.h"
int main()
{
    return a();
}


b.cpp
Код

#include "a.h"

int b()
{
    return a();
}


a.h
Код

#pragma once
int a()
{
    return 3 ;
}


Цитата

coll error LNK2005: _a already defined in a.obj
coll fatal error LNK1169: one or more multiply defined symbols found






--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
mr.Anderson
Дата 21.8.2005, 13:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


iOS Lead Developer
****


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

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



Ну, не знаю. Я описал свои функции работы с файлом в хедере, когда надо, я его подключаю. И все нормально вызывается и работает.
Добавлено @ 13:12
А "где угодно" - это где? И нафига тогда вообще хедер создавать?


--------------------
user posted image

user posted image
PM MAIL ICQ Skype   Вверх
Mayk
Дата 21.8.2005, 13:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


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

Репутация: 45
Всего: 134



Цитата(sim7 @ 21.8.2005, 17:11)
нафига тогда вообще хедер создавать?

Чтобы описывать прототипы ф-ций и классов. НЕ тела функций, а только объявления:
Код

int someFunc(void);

Тело
Код

int someFunc(void){
     //что-то очень страшное
     return 42;
}

по хорошему должно лежать в .cpp.



--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
mr.Anderson
Дата 21.8.2005, 14:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


iOS Lead Developer
****


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

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



Дык я вижу смысл создания хедера в том, чтобы по тридцать раз потом функцию-то не описывать! Создал один раз хедер, потом его подрубил и вызвал оттуда функцию, совершенно не вспоминая, а как же она написана. В этом и смысл хедера, я полагаю... Ведь мы, подключая файл <stdio.h>, не описываем функцию printf(), а просто вызываем и пользуемся ей, верно ведь?


--------------------
user posted image

user posted image
PM MAIL ICQ Skype   Вверх
Mayk
Дата 21.8.2005, 15:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


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

Репутация: 45
Всего: 134



Тело printf'а лежит в заголовке? Нет, там только объявление типа int printf(const char*fmt, ...);
Тело скомилированным лежит в библиотеке(кстати, еще одна причина по которой не стоит писать тела ф-ций в хедере - скорость компиляции проекта падает, так как один и тот же код компилится по тридцать раз).


--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
mr.Anderson
Дата 21.8.2005, 19:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


iOS Lead Developer
****


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

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



В библиотеке?! Это в DLL, что ли? А... Нда, спрашивать, как ее делать и как они взаимосвязаны, думаю, вы не ответите... smile smile


--------------------
user posted image

user posted image
PM MAIL ICQ Skype   Вверх
Denn
Дата 22.8.2005, 12:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Mayk
Если уж шаришь, поясни плиз. smile
Каким образом и в каком порядке подключаются хедеры? Почему, если в хедере объявлена функция, получается, что она подключается несколько раз, почему и этом случае не прокатывает #pragma once?
PM MAIL ICQ   Вверх
mr.Anderson
Дата 22.8.2005, 16:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


iOS Lead Developer
****


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

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



Mayk, ПЛИЗ! Скажите, как увязать DLL и хедер? И еще: создать DLL-библиотеку по учебнику я еще смогу, а вот как ее делать для таких вот консольных приложений? Объясните плиз сами или дайте ссылочку на нужную литературу.
Добавлено @ 16:32
И еще один вопрос забыл задать: что такое inline и static для функций? Для других случаев я знаю только для чего static в переменных. К примеру, что такое
Код

int i;
for(i=0;i<=100;++i)
{
 static x=0;
 ++x;
}
return x;

мне понятно. Т.е. тут x при новом проходе цикла не возвращается снова на ноль (если я правильно вспомнил этот пример из учебника...). Кстати, а const и static различны или нет по своему действию?
А вот что такое inline и что такое static для функций, прошу вас мне объяснить.

Это сообщение отредактировал(а) sim7 - 22.8.2005, 16:33


--------------------
user posted image

user posted image
PM MAIL ICQ Skype   Вверх
Mayk
Дата 22.8.2005, 17:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


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

Репутация: 45
Всего: 134



Вот, млин, навалились на Майка smile


Цитата(Denn @ 22.8.2005, 16:39)
Каким образом

Заместо директивы инклюд препроцессор вставляет и парсит содержимое файла. Следующие две конструкции ПОЛНСОТЬЮ эквивалентны для компилятора...
1)
a.cpp:
Код

int a();
int b(){return a();}

2) a.h
Код

int a();

a.cpp
Код

#include "a.h"
int b(){return a();}


...потому, что после прохода препроцессором по a.cpp получится код
Код

int a();
int b(){return a();}

который и будет передан компилятору

Цитата(Denn @ 22.8.2005, 16:39)
и в каком порядке подключаются хедеры?

в порядке объявления.

Цитата(Denn @ 22.8.2005, 16:39)

Почему, если в хедере объявлена функция, получается, что она подключается несколько раз, почему и этом случае не прокатывает #pragma once?


Потому что директива #pragma once означает, что данный файл не должен больше подключаться при компилировании именно этого объектного файла, а не какого-то другого(что вполне логично).
После прохода препроцессором по файлу a.cpp(мой предпредыдущий пост) получится следующий кот:

a_cpp_preprocessed:
Код

int a()
{
    return 3 ;
}
int main()
{
    return a();
}

Который будет успешно скомпилирован в a.obj. Значит, в файле a.obj будут содержаться следующие ф-ции:
Код

int a(void); 
int main(void);


После прохода препроцессором по b.cpp получится
Код

int a()
{
    return 3 ;
}
int b()
{
   return a();
}

Это тоже успешно скомпилируется. В файл b.obj будут содержаться сл-ие ф-ции:
Код

int a(void); 
int b(void);


Далее файлы a.obj и b.obj отдаются на съедение линкеру, который разбирает какую ф-ции из какого .obj/.lib выдрать.
И что же получает комрад линкер? Он получает 4 ф-ции:
int a(void); //из a.obj
int main(void); //из a.obj
int a(void); //из b.obj
int b(void); //из b.obj

встречая второе определение тела a() он, конечно, ругается.
#pragma once не существует для линкера. Где он должен её увидеть, эту pragma once?

Цитата(sim7 @ 22.8.2005, 20:27)
ПЛИЗ! Скажите,

[offtop]я предпочитаю обращение "ты"[/offtop]

Цитата
как увязать DLL и хедер?

Что означает "увязать .dll и хедер"?
Чтобы при объявлении ф-ции в хедере они вызывались из такой-то библиотеки? Ух,

mydll.h:
Код

extern int (*doSomethinhWonderful)(int);


loadmydll.cpp:
Код

int (*doSomethingWonderful)(int);


HINSTANCE myDll;
void loadMyDll()
{
    myDll = (HINSTANCE)LoadLibrary("mydll.dll");
    doSomethingWonderful=  (int (*)(int)) GetProcAddress(myDll, "myPuts");  
}

void test()
{
   doSomethingWonderful(1);
}

void unloadMyDll()
{
    FreeLibrary(myDll);
}

Что-то типа того. Но вообще один топик - один вопрос.
ЗЫ. Кстати, printf может подключатся совсем не из dll. Он может подключатся из статической либы - как если бы линкеру .obj подсунили.

Это сообщение отредактировал(а) Mayk - 22.8.2005, 19:14


--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
mr.Anderson
Дата 22.8.2005, 17:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


iOS Lead Developer
****


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

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



Вопрос 1: не можешь дать мне ссылку на более-менее понятную литературу по этому делу?
Вопрос 2: ты не ответил на вопросы о static и inline.
[offtopic]Ух, до того тяжело на "ты" обращаться, честное слово...[/offtopic]
Добавлено @ 17:28
Стоп, еще вопрос 3: объясните плиз пошагово строчку
Код

doSomethingWonderful=  (int (*)(int)) GetProcAddress(myDll, "myPuts");

Добавлено @ 17:29
Да, и еще: зачем еще раз объявлять функцию в твоем *.cpp-файле?
И еще: после extern обязательно должен быть тип int? А после него - обязательно скобки? Или что?


--------------------
user posted image

user posted image
PM MAIL ICQ Skype   Вверх
Mayk
Дата 22.8.2005, 18:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


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

Репутация: 45
Всего: 134



Цитата(sim7 @ 22.8.2005, 21:27)
не можешь дать мне ссылку на более-менее понятную литературу по этому делу?

http://forum.vingrad.ru/index.php?showtopic=33456
http://www.ozon.ru/?partner=vingrad
msdn.com
Цитата(sim7 @ 22.8.2005, 21:27)
ты не ответил на вопросы о static и inline.

Ах, да, точно. Если ф-ция объявлена как инлайн, то заместо ей вызова будет ее тело. Грубо говоря вот такого вот кота:
Код

inline void helloworld(int j)
{
   printf("hello world #%d\n",j);
}

int a()
{
   helloworld(very_horrible_expression); 
   normalFunction();
}

Компилятор переделает в нечто типа
Код

int a()
{
    //заместо helloworld(...)
    int helloworld_j=very_horrible_expression;
    printf("hello world #%d\n",helloworld_j);
    //далее тело a()
    normalFunction(); //вызов нормальной ф-ции
}


А если ф-ция(или переменная) объявлена как статик, то тогда она может быть вызвана только из того же объектного модуля, где определена. Для других объектных модулей она будет не видна.

Это сообщение отредактировал(а) Mayk - 22.8.2005, 18:59


--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
Mayk
Дата 22.8.2005, 19:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


^аВаТаР^ сообщение>>
****


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

Репутация: 45
Всего: 134



Цитата(sim7 @ 22.8.2005, 21:27)
объясните

smile

Цитата(sim7 @ 22.8.2005, 21:27)
GetProcAddress(myDll, "myPuts");

Загрузить из библиотеки ф-цию "myPuts". Ф-ция вернет нечто близкое к void*.
Цитата(sim7 @ 22.8.2005, 21:27)
(int (*)(int))

Закастить тип загруженной ф-ции - указатель на ф-цию принимающий 1 int и возвращающей int.
Цитата(sim7 @ 22.8.2005, 21:27)
doSomethingWonderful=

Присвоить указателю значение другого указателя.

Цитата(sim7 @ 22.8.2005, 21:27)
Да, и еще: зачем еще раз объявлять функцию в твоем *.cpp-файле?

Ключевою слово extern говорит о том, что данная вещь будет объявлена позже, возможно в другом объектном файле.


Цитата(sim7 @ 22.8.2005, 21:27)
И еще: после extern обязательно должен быть тип int? А после него - обязательно скобки? Или что?

Цитата(Mayk @ 22.8.2005, 21:18)
extern int (*doSomethinhWonderful)();

Попробую пошагово объяснить.

Код
extern 

Мы просто говорим компилятору о том, что есть такая глобальная переменная.

Цитата
int (*doSomethinhWonderfull(int)

имя переменной
Цитата
int (*doSomethinhWonderfull(int)

аргументы ф-ции.
Цитата
int (*doSomethinhWonderfull(int)

возвращаемое значение ф-ции
Цитата
int (*doSomethinhWonderfull(int)

Цитата
int (*doSomethinhWonderfull[b](int)

указатель на ф-цию принимающей инт и возвращающей инт.

Это сообщение отредактировал(а) Mayk - 22.8.2005, 19:13


--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
mr.Anderson
Дата 22.8.2005, 19:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


iOS Lead Developer
****


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

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



Цитата
smile

Вот-вот. Вы же сами сказали: "я люблю обращение на 'ты'"! А теперь злитесь. Так что я буду обращаться на "вы", так проблем меньше.
Объяснения хорошие, спасибо!


--------------------
user posted image

user posted image
PM MAIL ICQ Skype   Вверх
Void
Дата 22.8.2005, 20:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


λcat.lolcat
****


Профиль
Группа: Участник Клуба
Сообщений: 2206
Регистрация: 16.11.2004
Где: Zürich

Репутация: 40
Всего: 173



Цитата(Mayk @ 22.8.2005, 20:57)
Если ф-ция объявлена как инлайн, то заместо ей вызова будет ее тело.

Маленькое уточнение: это только подсказка компилятору подставить тело функции. Он вправе и не делать этого. А вправе и сделать без прямого указания в виде inline.
Но одно стабильно - inline функции, так же как static, имеют internal linkage, то есть не видны вне данной единицы трансляции.


--------------------
“Coming back to where you started is not the same as never leaving.” — Terry Pratchett
PM MAIL WWW GTalk   Вверх
Hroft
Дата 23.8.2005, 12:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Этот топик в юмор бы надо... smile
Стыдно должно стать, sim7, на такие вопросы можно найти ответы в начале любой книги по С++. По-моему, Страуструп "The C++ PL" маст хев и бест чойс в одном.
ЗЫ: sim7, а что, обращение "объясните" теперь уже считается обращением на ты?
PM MAIL ICQ   Вверх
mr.Anderson
Дата 23.8.2005, 15:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


iOS Lead Developer
****


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

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



Пардон, этого я и не заметил. Вот видите, привычка. Ну привык я обращаться на вы. Не понимаю, что тут такого неприятного...


--------------------
user posted image

user posted image
PM MAIL ICQ Skype   Вверх
Страницы: (3) [Все] 1 2 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




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


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

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