Ошибка Visual Studio C2061: синтаксическая ошибка: идентификатор

//Species.h
#pragma once
#include <iostream>
#include <string>
using namespace std;
class Species
{
protected:
    int HP, GroundAttack, AirAttack, MoveMode;
public:
};

// Protoss.h
#pragma once
#include "Species.h"
#include "Terran.h"

class Protoss : public Species
{
protected:
    int PS;
public:
    virtual void Input();
    virtual void Output();
    void B_AbilityAttack_A(Terran *);
};

// Terran.h
#pragma once
#include "Species"
#include "Protoss.h"

class Terran : public Species
{
public:
    virtual void Input();
    virtual void Output();
    void A_AbilityAttack_B(Protoss *);
};

"ошибка C2061: синтаксическая ошибка: идентификатор "терран""

"ошибка C2061: синтаксическая ошибка: идентификатор "Protoss""

ошибка в: void A_AbilityAttack_B(Protoss *) and void B_AbilityAttack_A(Terran *)

Как это исправить?

После исправления в методе класса Protoss я написал:

void Protoss::B_AbilityAttack_A(Terran *x)
{
    if (this->AbilityAttack() == 0 && x->GetMoveMode() == 0)
    {
        x->SetHP(x->GetHP() - this->GAttack());
    }
    else if (this->AbilityAttack() == 1 && x->GetMoveMode() == 0)
    {
        x->SetHP(x->GetHP() - this->GAttack());
    }
    else
    {
        x->SetHP(x->GetHP() - this->AAttack());
    }
}

И ошибка в x: «указатель на неполный тип класса не разрешен»

Итак, как это исправить?


person Pooh    schedule 10.07.2015    source источник
comment
Вы можете удалить #include "Protoss.h" из Terran.h и вместо этого написать class Protoss;.   -  person Dmitriy Zakablukov    schedule 10.07.2015


Ответы (1)


У вас круговая зависимость. Удалите включение Protoss на Terran и наоборот, вместо этого используйте предварительные объявления.

// Protoss.h
#pragma once
#include "Species.h"

class Terran;
class Protoss : public Species
{
protected:
    int PS;
public:
    virtual void Input();
    virtual void Output();
    void B_AbilityAttack_A(Terran *);
};

// Terran.h
#pragma once
#include "Species"

class Protoss;
class Terran : public Species
{
public:
    virtual void Input();
    virtual void Output();
    void A_AbilityAttack_B(Protoss *);
};

Это будет работать, потому что вам не нужны полные определения классов, потому что аргументы являются указателями, вам просто нужно объявить их вперед.

person Cory Kramer    schedule 10.07.2015
comment
Не забудьте повторно добавить включения в файлы cpp. - person KABoissonneault; 10.07.2015
comment
Также можно использовать указатель Species* вместо Terran* и Protoss*, потому что эти классы являются производными от класса Species. В этом случае нет необходимости использовать предварительное объявление. - person Dmitriy Zakablukov; 10.07.2015
comment
@DânNguyễn Все форматирование теряется в разделе комментариев. Если вы хотите уточнить свой вопрос и включить этот код, отредактируйте исходный вопрос. - person Cory Kramer; 10.07.2015
comment
@DânNguyễn Когда вы удаляете #include из файла .h, чтобы использовать предварительное объявление, вы должны добавить #include в файл .cpp, чтобы получить полное определение класса при попытке использовать этот тип. - person Cory Kramer; 10.07.2015