Your're instantiating an object y2
of incomplete type yyy
here:
{ a = 20; yyy y2; y2.show(); }
Move the implementation of constructor below the definition of yyy
class:
class yyy;
class xxx {
private:
int a;
public:
xxx();
void show() { cout << "a=" << a << endl; }
friend class yyy;
};
class yyy {
private:
int b;
public:
yyy() { b = 10; }
void show() { cout << "b=" << b << endl; }
};
xxx::xxx() { a = 20; yyy y2; y2.show(); } // No error
As a result, at this point yyy
is already defined, and you can instantiate y2
.
To give you a logical explanation, why your variant didn't work: when you instantiate an object with automatic storage duration (on stack) like yyy y2;
, compiler has to know at compile-time how much memory it should reserve for y2
. Since the yyy
type is incomplete (was only forward declared at the point of instantiation), the compiler is lost and reports an error.
NOTE: The best practice, is of course to separate definition of the class and its implementation by moving definition to header file (.hpp
) and implementation to source file (.cpp
). Don't forget to include headers properly. I don't feel like giving you an example here because it's very basic stuff and should be covered by any C++ book or a tutorial.