Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 03.11.2011, 17:52   #1
asmars
Форумчанин
 
Аватар для asmars
 
Регистрация: 28.05.2011
Сообщений: 309
По умолчанию Создание библиотек. Файлы ".h".

Доброго времени суток, господа!

Решил более структурировано писать на С++. Я начинающий.

1.Файлы .h, которые подключаются в начале кода, зачем они нужны. Это библиотеки, или заголовки?
2.В чем разница библиотек и заголовков?
3.Допустим у меня есть 10 ф-ций, я хочу вынести их в отделенный файл (библиотеку). Как это все реализовать ?

Заранее спасибо, господа.
Спеши медленно.
asmars вне форума Ответить с цитированием
Старый 03.11.2011, 17:57   #2
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

Цитата:
1.Файлы .h, которые подключаются в начале кода, зачем они нужны. Это библиотеки, или заголовки?
.h==Header File.
заголовочник.
он содержить(поидее должен) только обьявления функций/типов и тп.(искл шаблоны)
Цитата:
2.В чем разница библиотек и заголовков?
*.lib/lib*.a файлы содержат именно реализацию функций, методов и тп.
Цитата:
3.Допустим у меня есть 10 ф-ций, я хочу вынести их в отделенный файл (библиотеку). Как это все реализовать ?
ну собственно компилировать как библиотеку, более подробно надо знать компиль(и если это gcc, то IDE).
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 03.11.2011, 18:36   #3
asmars
Форумчанин
 
Аватар для asmars
 
Регистрация: 28.05.2011
Сообщений: 309
По умолчанию

Спасибо.
Но какова роль .h файлов?
Они как то связаны с библиотекой, верно?

Комилю я в Борланд Билдере 6..
Но как сделать свою библиотеку в которой подряд будут просто написана ф-ции и процедуры, и что бы я подключал этот файл к основной проге и просто вызывал эти ф-ции.. ??
Спеши медленно.
asmars вне форума Ответить с цитированием
Старый 03.11.2011, 18:51   #4
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

Цитата:
Но какова роль .h файлов?
чтоб компилятор знал аргументы и типы возврата функций/методов, и тп.
Цитата:
Они как то связаны с библиотекой, верно?
ну да, так как библиотека всетаки хоть и хранит(и то не всегда) инфу о типах данных, но она используется линкером, а не самим компилем.
Цитата:
Но как сделать свою библиотеку в которой подряд будут просто написана ф-ции и процедуры, и что бы я подключал этот файл к основной проге и просто вызывал эти ф-ции.. ??
библиотеки обычно состоят из пары .h+.lib(или иной формат)

про борланд не знаю.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 03.11.2011, 20:59   #5
Abstraction
Старожил
 
Аватар для Abstraction
 
Регистрация: 25.10.2011
Сообщений: 3,178
По умолчанию

Во-первых, если только у Вас нет веских причин держаться Борланда, уйдите с него. Дело в том, что господа Embarcadero пытались "усовершенствовать" C++, создав при этом заметно отличающийся диалект; часть этих наработок ушла в язык C#.
Как альтернативы, можно рассматривать Qt от Trolltech-Nokia или C++ express от Microsoft.

Во-вторых. В рамках одного проекта все современные среды разработки позволяют с лёгкостью использовать множественные файлы кода (Borland называет их Units). Это удобно, так как позволяет часть кода сосредоточить в одном "модуле", в который (если код в нём выверен и отлажен) заглядывать в дальнейшем не понадобится, а надо будет только вызывать функции. Кроме того, это позволяет скомпилировать код из файла в "почти" машинный код один раз, и лишь чуть-чуть менять при изменении прочих частей проекта, что сокращает время компиляции (не самый большой выигрыш на маленьких модулях, но привыкать полезно сразу). Однако кроме сгенерированного "почти машинного" кода, коль скоро мы компилируем модули поштучно, нужно уметь объяснять компилятору, что вызов такой-то функции, которой в текущем модуле нет, действие тем не менее легальное - она встретится в будущем.
Рассмотрим пример: мы собрались написать несколько полезных функций для вычислений в отдельном модуле. В файле MyMath.cpp пишем:
Код:
/*---------------------------------------------------------
 *    Библиотека математических функций
 *       написана Abstraction, 03.11.2011
 *     лежит в пространстве имён MyMath
 *--------------------------------------------------------*/

//Чтобы не думать о том, что выбранные мной названия случайно могут совпасть
//с системными, используется такая полезная штука, как пространство имён
namespace MyMath{
 
//Функция вычисления факториала
//Возвращает значение n!, если оно влезает в int
//Если же скормили слишком много или отрицательное число - возвращает -1
//(факториал от отрицательного целого числа неопределён)
//Поскольку факториал растёт ОЧЕНЬ быстро, проще не исхитряться с умножением в цикле,
//а сделать так:
//Создаём глобальный массив возможных значений (g_ в начале имени удобно приписывать
//всем глобальным переменным - так исчезает риск случайного совпадения имени с локальной переменной
int g_factorialValues[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880,
				3628800, 39916800, 479001600};//Для 64-разрядного int допишите сами
//И саму функцию
int Factorial(int n){
    if( n<0 || n>12 ) return -1;
    return g_factorialValues[n];	
}

//Биноминальный коэффициент, число сочетаний из n по k.
//Возвращает C(n, k) при n>=0, 0 при n<0, либо -1, если зафиксировано переполнение
//Реализуем через рекурсию
int Binominal(int n, int k){
	//Если k вылетело за пределы [0, n], ответ 0
	if(k<0 || k>n) return 0;
	//Если n<0, по нашим соглашениям ответ 0
	if(n<0) return 0;
	//Если k=n или 0, коэфффициент равен 1
	if(k==n || k==0) return 1;
	//А в остальных случаях,
	int c1=Binominal(n-1, k);
	int c2=Binominal(n-1, k-1);
	int ret = c1+c2;
	//Проверка переполнения
	if(ret<c1 || c1==-1 || c2==-1) return -1;
	return ret;
}

}//закрываем пространство имён
В файле Program.cpp пишем:
Код:
#include <iostream>

//Нам необходимо сказать компилятору: всё в порядке, есть среди прочих файлов проекта такие функции
int MyMath::Factorial(int n);
int MyMath::Binominal(int n, int k);

int main(void){
    int sample;
	
    std::cin >> sample;
	
    std::cout << MyMath::Factorial(sample);

    return 0;
}
Какие мы видим недостатки? Ну, во-первых, если я решу переименовать функцию в модуле MyMath, мне придётся шариться по всем прочим файлам проекта и проводить переименование.
Во-вторых, обратите внимание на комментарии к функциям: они явно распадаются на две части - как функцию использовать (то, что интересно при использовании модуля, интерфейс) и как она реализована (то, что интересно при написании модуля, реализация). Второе есть желание скрыть - какое дело использующему библиотеку, как именно я её создавал?
В-третьих, при этом любому пользователю модуля-библиотеки неизбежно открываются подробности, которые ему лучше бы не знать - например, информация о существовании g_factorialValues. От этого недалеко до того, чтобы обратиться к массиву самому, после чего я решу по какой-то причине переписать реализацию факториала, не меняя интерфейс и считая, что теперь достаточно только пересобрать проект - а вместо этого здравствуйте, ошибки в программе!
Abstraction вне форума Ответить с цитированием
Старый 03.11.2011, 20:59   #6
Abstraction
Старожил
 
Аватар для Abstraction
 
Регистрация: 25.10.2011
Сообщений: 3,178
По умолчанию

Поэтому библиотеку можно переписать, разбив на два файла:
MyMath.h
Код:
/*---------------------------------------------------------
 *    Библиотека математических функций
 *       написана Abstraction, 03.11.2011
 *     лежит в пространстве имён MyMath
 *--------------------------------------------------------*/

//Чтобы не думать о том, что выбранные мной названия случайно могут совпасть
//с системными, используется такая полезная штука, как пространство имён
namespace MyMath{
 
//Функция вычисления факториала
//Возвращает значение n!, если оно влезает в int
//Если же скормили слишком много или отрицательное число - возвращает -1
//(факториал от отрицательного целого числа неопределён)
int Factorial(int n);

//Биноминальный коэффициент, число сочетаний из n по k.
//Возвращает C(n, k) при n>=0, 0 при n<0, либо -1, если зафиксировано переполнение
int Binominal(int n, int k);

}
Это в чистом виде "заявки", ничего из них не компилируется в реальный код. И MyMath.cpp, который остаётся без изменений: при переделке реализации знать об интерфейсе необходимо, а вот в обратную сторону не обязательно.
Директива препроцессора #include "Имя файла" берёт текст файла и вставляет его вместо этой строки, это простая текстовая замена в исходном коде (как и большинство инструкций препроцессора). То есть, файл Program.cpp теперь видоизменился:
Код:
#include <iostream>

//Нам необходимо сказать компилятору: всё в порядке, есть среди прочих файлов проекта такие функции
#include "MyMath.h"

int main(void){
    int sample;
	
    std::cin >> sample;
	
    std::cout << MyMath::Factorial(sample);

    return 0;
}
Среда разработки при добавлении нового .cpp - файла к проекту автоматически соображает, что его надо будет компилировать вместе с прочими, так что программисту достаточно выбрать пункт меню "добавить новый файл кода к проекту", или как-то там.
Теперь пара замечаний.
1) Из-за того, что #include подставляет вместо себя текст файла, в заголовочных файлах категорически не рекомендуется использовать директиву using namespace. В cpp-файлах это делать можно, но после последней из директив #include.
2) При сложной структуре включений, может получиться так, что один и тот же заголовочный файл в данном модуле возникнет в двух экземплярах. Два одинаковых объявления - это ошибка, так что препроцессору в заголовочном файле надо как-то сказать "эй, если при обработке текущего (.cpp) файла меня уже видел, всё, второй раз подставлять не надо". Классическое решение - т.н. "стражи включения". В начало MyMath.h пишем
Код:
//Препроцессор! Если ты меня (__MYMATH_H) ещё не видел
#ifndef __MYMATH_H 
//Запомни: меня зовут __MYMATH_H
#define __MYMATH_H
А в конце
Код:
//Всё, я кончился
#endif
Что это значит? То, что при первой встрече препроцессор сообразит, что имя __MYMATH_H ему незнакомо (нужно любое название макроса, которое заведомо не встретится ни в каком другом файле), условие ifndef (if-not-defined) выполнено и воспримет весь текст до #endif. А вот при второй встрече имя будет знакомо, и препроцессор сразу "проскочит" до #endif, пропуская весь текст файла.
Могут быть доступны и другие способы - так, в Visual Studio достаточно написать в начале файла #pragma once.
Abstraction вне форума Ответить с цитированием
Старый 03.11.2011, 21:26   #7
asmars
Форумчанин
 
Аватар для asmars
 
Регистрация: 28.05.2011
Сообщений: 309
По умолчанию

Abstraction, благодарю Вас за объяснение! Прекрасно объяснили!


Цитата:
Во-первых, если только у Вас нет веских причин держаться Борланда, уйдите с него.
Скажите, что не так с Борландом?
И почему следует закинуть его? В принципе я могу и в MS Visual Studio(ее я не люблю!!), могу под линью писать и компилить gcc.
Но что вызвало такое к Борланду?
Спеши медленно.
asmars вне форума Ответить с цитированием
Старый 03.11.2011, 21:51   #8
Abstraction
Старожил
 
Аватар для Abstraction
 
Регистрация: 25.10.2011
Сообщений: 3,178
По умолчанию

Объяснение приведено: у Borland немного свой диалект C++, поэтому для учебных целей его использовать не самая лучшая идея. Главный кошмар - индексы, потому что Borland во многом наследник Delphi, в итоге, когда я на нём пишу, развлечение "угадай, какой индекс имеет первый элемент этого массива" предоставляется в достойных изумления количествах (AnsiString, скажем). Поскольку "недолёт/перелёт на единицу" и так достаточно частая проблема, я бы не усугублял.
Кроме того, Borland C++ 6 (это уже лично у меня) пару раз падал, настойчиво требует права администратора для работы, на днях поставил рекорд в номинации "самая тормозная подстановка по Ctrl+Space", приложение тащит за собой борландовские .bpl-библиотеки (причём отдельным пунктом идёт весёлая игра "угадай, из чего состоит минимальный набор"), автоподстановка как-то болезненно реагирует на шаблоны, запрещено встраивание (inlining) функций, содержащих циклы (за что?!), отрисовываемые формы не дружат с Aero... Сверх того, у него всё-таки устаревший отладчик: при вылете за пределы массива в режиме отладки мне маловато проку от ассемблерного кода, я в него лезть не хочу.
Ничего фатального, конечно, но неприятно, неприятно.
Abstraction вне форума Ответить с цитированием
Старый 03.11.2011, 21:56   #9
asmars
Форумчанин
 
Аватар для asmars
 
Регистрация: 28.05.2011
Сообщений: 309
По умолчанию

А что бы Вы посоветовали ?
Но с учетом того что "понадобиться в будущем".
Спеши медленно.
asmars вне форума Ответить с цитированием
Старый 03.11.2011, 22:12   #10
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

Цитата:
могу под линью писать и компилить gcc.
gcc и под винду есть.
Цитата:
Но с учетом того что "понадобиться в будущем".
MSVC++2010E или MinGW/gcc.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
при вводе на листе "магазин"- код товара появлялось "описание" товара из "склада" с "продажной ценой" aleksei78 Microsoft Office Excel 13 25.08.2009 12:04
настроить при открытии Excel 2003 в окошке "Тип файлов" вывод пункта "Все файлы (*.*)" по умолчанию? Unior Microsoft Office Excel 2 01.03.2009 02:42
"Текстовые файлы" и "Графика и подпрограммы" Nata!!!@ Помощь студентам 5 05.12.2007 18:17