jeudi 27 octobre 2016

Type info required in a class that's not actually using that type

So I'm having the following files, with the following content:

a.h :

#ifndef A_H
#define A_H

class A {
};

#endif

b.h :

#ifndef B_H
#define B_H

#include <memory>

class A;

class B {
public:
    B(std::unique_ptr<A> a);
private:
    std::unique_ptr<A> a_;
};
#endif

b.cpp :

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

B::B(std::unique_ptr<A> a) : a_(std::move(a)) {
}

c.h :

#ifndef C_H
#define C_H

#include "b.h"

class C {
public:
    void add_b(std::unique_ptr<B> b);

private:
    std::unique_ptr<B> b_;
};

#endif

c.cpp:

#include "c.h"

void C::add_b(std::unique_ptr<B> b) {
    b_ = std::move(b);
}

And a file containing an empty main method. As you can see in b.h I'm not actually including a.h since I'm using only pointers in the class declaration and that's not necessary, only a declaration being enough - class A;. If i try to compile this using gcc I'm getting an error that states something like:

In file included from /usr/include/c++/5/memory:81:0, from b.h:4, from c.h:4, from c.cpp:1: error: invalid application of ‘sizeof’ to incomplete type ‘A’
static_assert(sizeof(_Tp)>0

When I saw the part with "incomplete type 'A'" I figured out that class C needs more info about A since it's not aware of it's existence because it's only including b.h which only uses a declaration for A (class A;). Obviously including a.h header in c.cpp solved the error, but then I realized that A is not actually involved in the visible implementation of C class. Why does C need to know more info about class A? What's actually happening? I think this is very obscure and hard to follow. How can I avoid such situations? The original example was much more convoluted so I had to actually dig and simplify this. I was just trying to have a minimal header file with necessary info only, avoiding unnecessary macro expansions.

Aucun commentaire:

Enregistrer un commentaire