Чи слід використовувати передові декларації замість включень, де це можливо?
Ні, явні прямі декларації не повинні розглядатися як загальне керівництво. Переадресаційні декларації - це, по суті, копія та вставка, або неправильно написаний код, який у разі виявлення помилки в ньому потрібно виправити всюди, де використовуються переадресовані оголошення. Це може спричинити помилки.
Щоб уникнути невідповідності між "прямими" деклараціями та його визначеннями, покладіть декларації у файл заголовка та включіть цей файл заголовка як у визначальний, так і у вихідні файли, що використовують декларацію.
Однак у цьому спеціальному випадку, коли лише непрозорий клас оголошується вперед, це пряме оголошення може бути нормально використовувати, але загалом, "використовувати переадресовані оголошення, а не включати, коли це можливо", як заголовок цього потоку, може, бути досить ризикованим.
Ось кілька прикладів "невидимих ризиків" щодо прямих оголошень (невидимі ризики = невідповідність оголошень, які не виявляються компілятором або компонувальником):
Явні прямі декларації символів, що представляють дані, можуть бути небезпечними, оскільки такі прямі декларації можуть вимагати правильного знання розміру (розміру) типу даних.
Явні прямі декларації символів, що представляють функції, також можуть бути небезпечними, як-от типи параметрів і кількість параметрів.
Наведений нижче приклад ілюструє це, наприклад, дві небезпечні декларації вперед даних, а також функції:
Файл змінного струму:
#include <iostream>
char data[128][1024];
extern "C" void function(short truncated, const char* forgotten) {
std::cout << "truncated=" << std::hex << truncated
<< ", forgotten=\"" << forgotten << "\"\n";
}
Файл bc:
#include <iostream>
extern char data[1280][1024];
extern "C" void function(int tooLarge);
int main() {
function(0x1234abcd);
std::cout << "accessing data[1270][1023]\n";
return (int) data[1270][1023];
}
Компіляція програми з g ++ 4.7.1:
> g++ -Wall -pedantic -ansi a.c b.c
Примітка: Невидима небезпека, оскільки g ++ не видає помилок / попереджень компілятора або компонувальника.
Примітка: Опускання extern "C"
призводить до помилки прив'язки function()
через маніпулювання іменем c ++.
Запуск програми:
> ./a.out
truncated=abcd, forgotten="♀♥♂☺☻"
accessing data[1270][1023]
Segmentation fault