VC ++ 2010: ошибки «отсутствующего спецификатора типа» приходят и уходят без изменений в коде - PullRequest
1 голос
/ 22 ноября 2011

Предположим, есть четыре файла: foo.h, foo.cpp, bar.h, bar.cpp.

foo.h:

#pragma once

class foo
{
    // Whatever
};

foo.cpp

#include "foo.h"

// Foo's definitions

bar.h

#pragma once

class bar
{
    bar(const foo & f); // < C4430 'missing type specifier' (not always)
    // Other declarations
};

bar.cpp

#include "foo.h"
#include "bar.h"

// Bar's definitions

Компилятор говорит, что в bar.h есть C4430.Но странно то, что я могу создать код, комментируя и затем раскомментируя эту строку.Конечно, сборка завершается неудачно с комментируемой строкой, но когда я раскомментирую ее, я получаю успешную сборку.Поэтому один и тот же код может выдавать или не выдавать ошибки.

Моя VS - 10.0.40219.1 SP1Rel, а тип проекта - Win32 DLL.

1 Ответ

2 голосов
/ 22 ноября 2011

Вам необходимо включить foo.h в bar.h:

#pragma once

#include "foo.h"
class bar
{
    bar(const foo & f);
};

Если вам нужно полное определение класса, которое вы используете, если вы не используете указатель (в этом случае будет достаточно предварительного объявления), вам нужно включить файл, в котором объявлен класс.

Почему иногда он компилируется, а иногда не получается?

Зависит от компилятора. Я предполагаю, что foo.h включен в файл, который компилируется до достижения bar.h. Так что bar.h уже знает об определении foo. Если сборка не удалась, файлы, которые были успешно скомпилированы, пропускаются и, возможно, foo.h больше не включаются. Или, если вы внесете изменение только в x.cpp, компилятор будет только строить этот файл и, возможно, пропустить включение foo.h, которое было включено в файл, который уже скомпилирован.

Надеюсь, я был чист.

Почему того, что у вас уже есть, недостаточно?

Можно сказать, что

//Bar.cpp
#include "foo.h"
#include "bar.h"

// Bar's definitions

включает foo.h до bar.h. Действительно, но что, если bar.h включен до foo.h в другом месте? Вот почему хорошая идея включить foo.h в bar.h. Любой файл, включая bar.h, больше не должен включать foo.h (что необходимо для компиляции), и имеет смысл включить в файл все, что вам нужно. Это не относится к предварительным объявлениям, но, опять же, вы используете полный тип, а не указатель.

...