Как я могу использовать функцию-член объявленного вперед класса?

У меня есть 2 класса A и B и 4 следующих файла:

ах

#ifndef A_H
#define A_H

#include "B.h"
class A {
public:
    A();
    int functionA();
    B objectB;
};

#endif //A_H

Bh

#ifndef B_H
#define B_H

class A;
class B {
public:
    B();
    int functionB();
    A * objectA;
};

#endif //B_H

a.cpp

#include "A.h"
A::A(){}
int A::functionA() {
    return 11;
}

B.cpp

#include "B.h"
B::B(){}
int B::functionB() {
    return objectA->functionA();
}

Теперь я компилирую, используя строку: g++ A.cpp B.cpp -Wall -Wextra -O2 -march=native -std=gnu++1z

Я получаю эту ошибку:

B.cpp: In member function 'int B::functionB()':
B.cpp:4:19: error: invalid use of incomplete type 'class A'
     return objectA->functionA();
                   ^
In file included from B.cpp:1:0:
B.h:1:7: note: forward declaration of 'class A'
 class A;
       ^

Как я могу использовать класс-член функции forward, объявленной здесь?

3 ответа

Решение

Посмотрите, что включено при компиляции B.cpp, у вас есть предварительное объявление класса A но не настоящее определение. Так в B.cpp в строке 4, functionA компилятору неизвестно, поэтому ваш тип неполон.

Вы должны включить A.h в B.cpp,

В A.cpp Включите оба A.h а также B.h
В B.cppВключите оба B.h а также A.h,

Это работает потому что:

  1. У нас нет циклического включения (файл заголовка, который включает в себя другой файл заголовка, который включает в себя оригинал)
  2. Каждая реализация класса "видит", как выглядит другой класс, но не как он реализован, мы не нарушаем правило "отделение интерфейса от реализации". В некоторых случаях мы этого не делаем, но в большинстве случаев это действительно.

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

Использование членов класса только с предварительным объявлением невозможно.

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

Другие вопросы по тегам