Использование типа undefined

#include <iostream>

class Core;
class State;

int main (){
        std::cin.get();
        return 0;
}

class State{
public:
    State(Core* core){
        core->setState();
    }
};

class Core{
public:
    Core(){
        State state(this);
    }
    void setState(){
        std::cout << "setting state" << std::endl;
    }
};

Я продолжаю "использовать ошибку типа undefined". Я думал, что если я переведу объявить оба класса, это исправит проблему, но я не могу понять это. Это просто глупый синтаксис С++, который мне не хватает?

РЕДАКТИРОВАТЬ: Извините за оговорку о галактике, я изменил ее на состояние и все еще производит ошибку.

Ответ 1

В State::State вы используете Core, прежде чем он будет определен. Вы можете легко это исправить в своем примере:

class State{
public:
    State(Core* core);
};

class Core{
   // This stays the same...
};

State::State(Core* core)
{
   core->setState();
}

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

В этом случае:

// State.h
class Core

class State{
public:
    State(Core* core);
};

и

// Core.h
#include "State.h"

class Core{
public:
    Core(){
        State state(this);
    }

    void setState(){
        std::cout << "setting state" << std::endl;
    }
};

И файл реализации:

// State.cpp
#include "State.h"
#include "Core.h"

State::State(Core* core)
{
   core->setState();
}

Ответ 2

Вы можете перенаправить объявление типа, когда вам нужно только указать имя, например, для создания указателей, ссылок, аргументов значений функций или возвращаемых типов. Если вы в значительной степени используете его, например, в определении функции или разыменовывая указатель, вам нужно определение. Способ решения проблемы состоит в том, чтобы объявить функцию-член, но не определять ее в определении класса State. Вместо этого вы бы определили его, как только было определено определение Core:

State::State(Core* core){
    core->setState();
}