Как я могу использовать функцию-член объявленного вперед класса?
У меня есть 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
,
Это работает потому что:
- У нас нет циклического включения (файл заголовка, который включает в себя другой файл заголовка, который включает в себя оригинал)
- Каждая реализация класса "видит", как выглядит другой класс, но не как он реализован, мы не нарушаем правило "отделение интерфейса от реализации". В некоторых случаях мы этого не делаем, но в большинстве случаев это действительно.
Правило большого пальца (только правило большого пальца!) Должно включать заголовок класса в каждый .cpp
файл, который использует этот класс. так что если foo.cpp
использует класс bar
и класс bar
интерфейс находится в bar.h
, затем foo.cpp
должны включать bar.h
, В некоторых случаях мы не следуем этому правилу, но в большинстве случаев оно действительно.
Использование членов класса только с предварительным объявлением невозможно.
Если ваш код использует функцию-член, класс должен быть полностью объявлен, потому что компилятор должен проверить, что функция-член с таким именем действительно существует.