Как правильно подключать файлы?

Вылетает ошибка "Member access into incomplete type 'C'" в файле A.h при объявлении функции funC(). Знаю, что такую ошибку можно исправить объявив функцию в классе, а реализовать в main.cpp. Но так же находил ответы, что можно решить путем разделения кода на файлы .cpp и .h. Не совсем понимаю как правильно разделить. Можете привести пример правильного разделения?

main.cpp

#include <iostream>
#include "A.h"
#include "B.h"
#include "C.h"

int main() {

    return 0;
}

A.h

#ifndef A_h
#define A_h

class C;
class B;

class A {

    int numA = 0;

public:
    int getNum () {return numA;}

    void funC (C &c, B &b) {

        std::cout << c.getNum() << " " << b.getNum() << std::endl;
    }
};

#endif

B.h

#ifndef B_h
#define B_h

class A;
class C;

class B {

    int numB = 1;

public:
    int getNum () {return numB;}

    void funC (A &a, C &c) {

        std::cout << a.getNum() << " " << c.getNum() << std::endl;
    }
};

#endif

C.h

#ifndef C_h
#define C_h

class A;
class B;

class C {

    int numC = 3;

 public:
    int getNum () {return numC;}

    void funC (A &a, B &b) {

        std::cout << a.getNum() << " " << b.getNum() << std::endl;
    }

};

#endif 

Ответы (1 шт):

Автор решения: Mikhailo

У вас в h-файле не только объявления, и в этом проблема. Например, в С.h:

void funC (A &a, B &b) {

    std::cout << a.getNum() << " " << b.getNum() << std::endl;
}

Пока вы пишете

void funC (A &a, B &b);

компилеру достаточно знать, что есть такие классы - A и B, и его устраивает неполное объявление

class A;
class B;

Но тут

    std::cout << a.getNum() << " " << b.getNum() << std::endl;

ему нужно знать, что такое getNum для A и B - что это за функции, что возвращают - а это ему знать неоткуда.

Поэтому в таких ситуациях выносите реализацию из класса, пока клаасс, на который ссылаетесь, не будет объявлен полностью.

Я все сложил в один файл для простоты понимания. Вот так у вас -

#include <iostream>

class A;
class B;
class C;

class A {

    int numA = 0;

public:
    int getNum () {return numA;}

    void funC (C &c, B &b) {

        std::cout << c.getNum() << " " << b.getNum() << std::endl;
    }
};

class B {

    int numB = 1;

public:
    int getNum () {return numB;}

    void funC (A &a, C &c) {

        std::cout << a.getNum() << " " << c.getNum() << std::endl;
    }
};

class C {

    int numC = 3;

 public:
    int getNum () {return numC;}

    void funC (A &a, B &b) {

        std::cout << a.getNum() << " " << b.getNum() << std::endl;
    }

};

int main()
{
}

и не компилируется.

А вот так все работает:

#include <iostream>

class A;
class B;
class C;

class A {

    int numA = 0;

public:
    int getNum () {return numA;}
    void funC (C &c, B &b);
};

class B {

    int numB = 1;

public:
    int getNum () {return numB;}
    void funC (A &a, C &c);
};

class C {

    int numC = 3;

 public:
    int getNum () {return numC;}
    void funC (A &a, B &b);
};

void A::funC (C &c, B &b) {
    std::cout << c.getNum() << " " << b.getNum() << std::endl;
}
void B::funC (A &a, C &c) {
    std::cout << a.getNum() << " " << c.getNum() << std::endl;
}
void C::funC (A &a, B &b) {
    std::cout << a.getNum() << " " << b.getNum() << std::endl;
}




int main()
{
}
→ Ссылка