Joel
Joel

Reputation: 2035

Passing value between classes

I'm tryng to pass value between two classes:

#ifndef classa_inc
#define classa_inc

#include "classb.hpp"

class classa {
    private:
        int a;
        classb tmp;
    public:
        classa(int);
        classa ();
        int get_a() const;
        int get_b() const;
};

#endif

// ..

#include "classa.hpp"

classa::classa (int _a) : a(_a), tmp(30) {}
classa::classa () : a(20), tmp(30) {}

int classa::get_a () const {
    return a;
}

int classa::get_b () const {
    return tmp->get_b ();
}

// ..

#ifndef classb_inc
#define classb_inc

#include "classa.hpp"

class classa;

class classb {
    private:
        classa *ca;
        int b;
    public:
        classb (int);
        classb (classa *);
        int get_b () const;
};

#endif

// ..

#include "classb.hpp"

classb::classb (int _b) : b(_b) {}

classb::classb (classa *ca) {
    b = ca->get_a ();
}

int classb::get_b () const {
    return b;
}

// ...
#include <iostream>
#include "classa.hpp"
#include "classb.hpp"

int main () {
    classa a(10);
    classa a1; // 20
    classb b(&a1); // pass 20
    std::cout << a.get_a() << std::endl; // 10
    std::cout << a.get_b() << std::endl; // 30
    std::cout << b.get_b() << std::endl; // 20
    return 0;
}

I've reading some blogs and tutorials about the topic and I'd like to ask you guys if this the propper way of doing it or there are another way or workaround about doing it, because I got error:

classa.hpp:9:3: error: ‘classb’ no nombra a un tipo

Something like classb don't name a type...any ideas?

Upvotes: 0

Views: 89

Answers (2)

Beta
Beta

Reputation: 99172

Your classb.cpp:

#include "classb.hpp"

...

The compiler expands the #include macro, and inserts classb.hpp:

#ifndef classb_inc
#define classb_inc

#include "classa.hpp"
...
class classb {
...
};
#endif

...

It expands the new #include macro, and inserts classa.hpp:

#ifndef classb_inc
#define classb_inc

#ifndef classa_inc
#define classa_inc

#include "classb.hpp"

...
classb tmp;
...
#endif

class classb {
...
};
...
#endif

...

The compiler expands that #include macro, and inserts classb.hpp again:

#ifndef classb_inc
#define classb_inc  <--

#ifndef classa_inc
#define classa_inc

#ifndef classb_inc  <--
...
#endif

...
classb tmp;  <--
...
#endif

class classb {
...
};
...
#endif

...

Notice the two marked lines; the first defines classb_inc, so the second omits everything until the #endif. This is correct behavior for an include-guard. But now there is no definition of classb before the third marked line, and the compiler complains that it doesn't know what a classb is.

The solution: classb.hpp need not include classa.hpp.

#ifndef classb_inc
#define classb_inc

//#include "classa.hpp"

class classa;

class classb {
...
};

Upvotes: 2

Violeta Marin
Violeta Marin

Reputation: 90

In classb.hpp, the forward declaration of classa is sufficient (class classa;). You do not need to include classa.hpp. Including it will cause a circular dependency: classb.hpp includes classa.hpp, which also includes classb.hpp etc.

So:

#ifndef classb_inc
#define classb_inc

//#include "classa.hpp" -> not ok and useless

class classa; // => ok

classa.hpp needs to be included in classb.cpp, though, because it needs to know about its implementation.

#include "classb.hpp"
#include "classa.hpp" 

classb::classb (int _b) : b(_b) {}

classb::classb (classa *ca) {
    b = ca->get_a (); //needs to know if classa indeed has a get_a() method
}

int classb::get_b () const {
    return b;
}

Those changes made the code compile successfully.

Upvotes: 2

Related Questions