Созданный пользователем заголовок, вызывающий C2061: синтаксическая ошибка: идентификатор «имя класса» - PullRequest
8 голосов
/ 29 июня 2011

Итак, я ожидаю, что это в конечном итоге будет простым ответом, но я уже давно взломал его и, похоже, не могу решить эту проблему.Поэтому у меня есть определенный класс Intersection, который при включении в любой другой заголовок дает мне:

error C2061: syntax error : identifier 'Intersection'

Это мой заголовок пересечения:

#ifndef INTERSECTION_H
#define INTERSECTION_H

#include "Coord.h"
#include "Road.h"
#include "TrafficLight.h"

class Intersection {
private:
    int id;
    Coord * midPoint;
    Road * northRoad;
    Road * eastRoad;
    Road * westRoad;
    Road * southRoad;
    TrafficLight * trafficLight;
public:
    Intersection(int, Coord *, Road *, Road *, Road *, Road *);
    ~Intersection();
    void transitionTrafficLight();
    int getId();
    Road * getNorthRoad();
    Road * getEastRoad();
    Road * getWestRoad();
    Road * getSouthRoad();
    TrafficLight * getTrafficLight();
};

#endif

Теперь, если я попытаюсь использовать этот класс в другом месте, я получу ошибку.Например:

#ifndef ROAD_H
#define ROAD_H

#include "Coord.h"
#include "Intersection.h"
#include <string>

class Road {

public:
    enum LaneCount { TWO_LANE = 2, FOUR_LANE = 4 };
    Road(std::string, Coord *, Coord *, LaneCount, Intersection *, Intersection *, int);
//shortened

Особенно в конструкторе Road (и любых других классах, которые ссылаются на Intersection).Я не думаю, что это проблема синтаксиса, поскольку Coord - это другой класс, определенный таким же образом, и компилятор (VS 2008) не жалуется на это.В частности, это Intersection доставляет мне эту проблему.: /

Я отмечаю это домашнее задание - для этого оно и нужно, хотя это просто ошибка, от которой я не могу избавиться, а не часть проблемы.

Мысли?

1 Ответ

26 голосов
/ 29 июня 2011

Похоже, ошибка в том, что у вас есть два заголовочных файла, которые находятся по кругу друг в друге - intersection.h и road.h.Это может привести к странным сюрпризам в C ++ из-за того, как работают охранники включения.Например, предположим, что у меня есть два заголовочных файла, которые выглядят следующим образом:

// File: A.h
#ifndef A_Included
#define A_Included

#include "B.h"

class A {};

void MyFunction(B argument);
#endif

и

// File: B.h
#ifndef B_Included
#define B_Included

#include "A.h"

class B {};

void MyOtherFunction(A argument);
#endif

Теперь, если я попытаюсь #include "A.h", он расширится до

// File: A.h
#ifndef A_Included
#define A_Included

#include "B.h"

class A {};

void MyFunction(B argument);
#endif

Когда я пытаюсь расширить #include "B.h", я получаю это:

// File: A.h
#ifndef A_Included
#define A_Included

// File: B.h
#ifndef B_Included
#define B_Included

#include "A.h"

class B {};

void MyOtherFunction(A argument);
#endif

class A {};

void MyFunction(B argument);
#endif

В этот момент препроцессор снова попытается расширить A.h, что приводит к этому:

// File: A.h
#ifndef A_Included
#define A_Included

// File: B.h
#ifndef B_Included
#define B_Included

// File: A.h
#ifndef A_Included
#define A_Included

#include "B.h"

class A {};

void MyFunction(B argument);
#endif

class B {};

void MyOtherFunction(A argument);
#endif

class A {};

void MyFunction(B argument);
#endif

Теперь давайте посмотрим, что произойдет, когда мы разрешим все эти странные охранники.Когда мы видим A в первый раз, он расширяется, как и в случае, когда мы расширяем B впервые.Однако, когда мы видим A во второй раз, он вообще не раскрывается.Таким образом, после извлечения комментариев и директив препроцессора мы получаем следующий результирующий код:

class B {};
void MyOtherFunction(A argument);
class A {};
void MyFunction(B argument);

Обратите внимание, что когда объявлено MyOtherFunction, A еще не объявлено, и поэтому компилятор сообщает об ошибке.

Чтобы это исправить, вы можете заранее объявить A и B в заголовочных файлах, которым они нужны:

// File: A.h
#ifndef A_Included
#define A_Included

class A {};
class B;    // Forward declaration

void MyFunction(B argument);
#endif

и

// File: B.h
#ifndef B_Included
#define B_Included

class B {};
class A;    // Forward declaration

void MyFunction(B argument);
#endif

Теперь больше нет циклических зависимостей.Пока вы #include соответствующие заголовочные файлы в .cpp файлах, у вас все будет хорошо.

Надеюсь, это поможет!

...