为什么在这种情况下前向声明不起作用?

时间:2019-11-30 05:40:55

标签: c++

考虑以下示例:

a.h

#ifndef A_H
#define A_H

#include <vector>
#include <memory>
#include "b.h"

enum class SActionType;

class A {
    std::vector<std::unique_ptr<B>> my_bees;
public:
    A();
    void print(int x, int y);
};
#endif

a.cc

#include <iostream>
#include "a.h"

A::A() {
}

void A::print(int x, int y) {
    std::cout << "hi this is not going to work" << std::endl;
}

b.h

#ifndef B_H
#define B_H

#include <memory>
#include <vector>
// #include "a.h"

class A;
class B {
    std::shared_ptr<A> a;
public:
    B(std::shared_ptr<A> a);
    void foo();
};
#endif

b.cc

#include <algorithm>
#include "b.h"

B::B(std::shared_ptr<A> a):
    a{a}
{}

void B::foo() {
    a->print(1, 2);
}

main.cc

#include "a.h"
#include "b.h"

int main() {
    return 0;
}

Makefile

exec: main.o a.o b.o
    g++ -std=c++14 -o exec
main.o: main.cc
a.o: a.cc a.h
b.o: b.cc b.h

运行make后,出现以下错误:

me:~$ make
g++    -c -o b.o b.cc
b.cc: In member function ‘void B::foo()’:
b.cc:9:6: error: invalid use of incomplete type ‘using element_type = class A {aka class A}’
     a->print(1, 2);
      ^~
In file included from b.cc:2:0:
b.h:8:7: note: forward declaration of ‘using element_type = class A {aka class A}’
 class A;
       ^
<builtin>: recipe for target 'b.o' failed
make: *** [b.o] Error 1

为什么会这样?我认为这是可行的,因为类B实际上不需要访问A的成员函数,直到.cc文件为止,仅在头文件中包含前向声明就足以规避循环依赖。

2 个答案:

答案 0 :(得分:3)

  

我认为这是可行的,因为类B实际上不需要访问A的成员函数,直到.cc文件

是的。 b.h不需要包含a.ha.h也不需要包含b.h)。但是b.cc需要同时包含两者。对此没有任何通知。毕竟,a.cc做同样的事情。

b.cc
#include <algorithm>
#include "a.h"
#include "b.h"

B::B(std::shared_ptr<A> a):
    a{a}
{}

void B::foo() {
    a->print(1, 2);
}

答案 1 :(得分:0)

编译器需要知道要检查这种构造的A类的完整类型

void B::foo() {
    a->print(1, 2);
}

有效的是类A包含成员函数(静态还是非静态的)print