Как вы определяете глобальную функцию в С++?
Мне нужна функция, которая не является членом класса и доступна из любого класса.
Я предполагаю, что мне нужно #include
заголовочный файл, где объявлена функция, но я не знаю, где определить такую глобальную функцию.
Есть ли веские причины против такой функции в первую очередь?
Ответы
Ответ 1
вам нужно тело (в файле cpp
):
int foo()
{
return 1;
}
и определение/прототип в файле заголовка, который будет включен перед любым использованием функции:
#ifndef MY_FOO_HEADER_
#define MY_FOO_HEADER_
int foo();
#endif
затем используя его в другом месте:
#include foo.h
void do_some_work()
{
int bar = foo();
}
или использовать встроенную функцию (не гарантирует, что она будет встроена, но полезна для небольших функций, таких как foo
):
#ifndef MY_FOO_HEADER_
#define MY_FOO_HEADER_
inline int foo()
{
return 1;
}
#endif
альтернативно вы можете злоупотреблять функциями на основе заголовка C-стиля (так что это идет в заголовке, static
заставляет его существовать только в одном модуле компиляции, вы должны избегать этого):
#ifndef MY_FOO_HEADER_
#define MY_FOO_HEADER_
static int foo()
{
return 1;
}
#endif
Ответ 2
То, что вы называете глобальной функцией, обычно называется свободной функцией, и они Хорошая вещь.
Вы определяете его так же, как функцию-член класса, но вне области этого класса.
double squared(double x) {
return x*x;
}
Простые функции, которые вы можете определить с помощью ключевого слова inline
в файле заголовка или просто объявить его там
double squared(double x);
и поместите реализацию (первый пример) в файл *.cpp
.
Ответ 3
В файле заголовка:
// someheader.h
#ifndef MY_GLOBAL_FUN
#define MY_GLOBAL_FUN
void my_global_fun();
#endif
В файле реализации:
#include "someheader.h"
void my_global_fun()
{
// ...
}
В других файлах, требующих этой функции:
#include "someheader.h"
void f()
{
my_global_fun();
}
Свободные функции, подобные этому, полезны, и не так много аргументов против их использования. В зависимости от вашего варианта использования, вероятно, целесообразно разместить эти функции в определенном namespace
, чтобы избежать столкновения имен с другими библиотеками, которые вы можете использовать.
Ответ 4
Подумайте о main(). Функция вроде просто... есть. Он не входит ни в какой класс, структуру или пространство имен. Вы просто объявляете и даете ему тело. Конечно, в случае функций, которые не являются основными, лучше всего поставить прототип в заголовок и определить его в .cpp файле.
Помните, что у C не было классов, а структуры не могли содержать функции-члены. Тогда не было ничего плохого в свободных функциях, а теперь нет.
Ответ 5
Вы должны объявить свой прототип в файле заголовка и определить его в файле реализации.
//file.h
void foo();
//file.cpp
void foo ()
{}
Чтобы ответить на второй вопрос, нужны глобальные функции, когда они используются несколькими различными классами и типами в общем виде. Например, математические функции.
В противном случае вы можете избежать так многих глобальных функций. Также вам следует избегать наличия локального члена static
или глобальных данных, связанных с такой функцией (так что вам не нужно беспокоиться о безопасности потоков).
Ответ 6
В дополнение к ответу @Necrolis использование static устарело в пользу неназванных пространств имен. Однако использование неназванных пространств имен и статики создает отдельные копии для каждой единицы перевода, что увеличивает размер двоичного файла. Использование inline лучше, чем оба в этом смысле.
Эти решения позволяют больше оптимизировать работу с использованием компиляторов, но они менее дружественны к кешу по сравнению с определением в исходном файле и затем связаны.