Я заметил, что при связывании проекта с использованием G ++, если есть функции, которые объявлены, но не реализованы, ошибок нет, если только я не попытаюсь их вызвать.
Q1: Можно ли включить ошибку (или хотя бы предупреждение), если функция объявлена, но не реализована?
Q2: Почему это поведение?
(Замечания: я использую G++ 4.7.0
, ld 2.22
если это компоновщик, используемый gcc, из mingw
пакет)
A2: Объект, такой как не встроенная функция с внешней связью, может иметь ноль или одно определение в программе. Требуется иметь только одно определение, если оно действительно используется (строго УСО используемый) — например будучи призванным. g ++ был бы ошибочным, если бы он выдал ошибку для неопределенной функции, которая не использовалась.
A1: Таким образом, невозможно (соответствующим образом) заставить это быть ошибкой.
Написать юнит-тесты. Если функции нет, код, который тестирует ее, не будет выполнен.
Невозможно получить ошибку в одном модуле компиляции (во время компиляции), если функция объявлена только. Потому что эта функция может быть определена в другом модуле компиляции.
Вы могли бы (предполагая систему Linux с включенными плагинами в компиляторе) написать плагин GCC, или, лучше, ПЛАВИТЬСЯ расширение (MELT — это высокоуровневый предметно-ориентированный язык для расширения GCC), который, например, будет создавать массив указателей на каждую объявленную функцию (поэтому, если функция не определена, вы получите ошибку во время соединения). Вы также можете создать расширение MELT, которое будет предупреждать о каждой неопределенной, но объявленной функции.
Кроме того, иногда есть веские причины для объявления, но не определения функции, например, когда это должно быть предоставлено плагином, или другим объектом или библиотекой.
Кроме того, заголовочные файлы обычно объявляют функции, но не определяют их. Эти функции обычно предоставляются во время соединения библиотеками.
Вы можете заставить компоновщик генерировать ошибки для неуказанных, неопределенных функций-членов, делая их виртуальными. Очевидно, что это имеет другие последствия, поэтому я бы порекомендовал использовать для этого препроцессор. Что-то вроде:
#ifdef TEST_COMPLETE_INTERFACE
#define REQUIRE_DEF virtual
#else
#define REQUIRE_DEF
#endifclass myClass
{
public:
REQUIRE_DEF void someMethod();
};
Вы можете периодически проверять, что все строит с TEST_COMPLETE_INTERFACE
определены. Это не будет работать для статических методов или свободных функций.
Есть специфический атрибут GCC:
void f() __attribute__((error("not implemented")));
int main() {
f();
}
дает
error: call to 'f' declared with attribute error: not implemented
Этот атрибут также можно использовать в методах класса. Поддерживается, по крайней мере, GCC 4.4.