Reputation: 67
I complied the following code, and get error: incomplete type ‘AB::B’ used in nested name specifier
class B; //declareation
namespace A
{
class myException():public std::exception
{
public:
myException():std::exception()
{
B::b2(); //error: incomplete type ‘A::B’ used in nested name specifier
}
};
class B()
{
static void b1()
{
throw myException();
}
static void b2()
{
//code
}
};
};
I think I got a circular dependency between these two classes. Is it the reason that cause the error? How can I get arround the circular dependency?
Thanks a lot
Upvotes: 1
Views: 16185
Reputation: 254531
I think I got a circular dependency between these two classes.
Not between the classes themselves; but each has member functions that depend on the other class, so as written there is a circular dependency.
Is it the reason that cause the error?
Yes. Each member function definition has to come after the class that it uses; which is impossible if they are defined in the class.
How can I get arround the circular dependency?
Move the definition of at least one of the member functions out of its class, to a point at which the other class is defined. If these are in a header, intended to be included from multiple source files, then either move the definition to a source file, or to later on in the header with an inline
specifier.
For example, you could move the constructor of myexception
, leaving just a declaration in the class:
class myException():public std::exception
{
public:
myException(); // OK: no use of incomplete type here
};
and define it either inline, after the definition of B
, or in a source file that includes this header:
inline // if defined in a header
myException::myException() // no need to explicitly initialise std::exception
{
B::b2(); // OK: B is complete now
}
Upvotes: 3
Reputation: 206637
First of all,
class B; //declareation
namespace A
{
declares B
to be a class in the global namespace, not in namespace A
. Hence, the use of
B::b2();
later in the code expects b2
to be a member of the global B
. I think you meant to forward declare the B
in namespace A
. For that, you need to use:
namespace A
{
class B; //declareation
To remove the circular dependencies between the class definitions and the member function implementations, move the member function implementations after the classes have been defined. Then, you don't need the forward declaration of B
at all. It won't hurt if it's there, but it's not necessary.
namespace A
{
// Optional.
class B;
// Class definitions without the member function implementations
class myException(): public std::exception
{
public:
myException();
};
class B()
{
public:
static void b1();
static void b2();
};
// Class member function implementations
inline myException::myException(): std::exception()
{
B::b2();
}
inline void B::b1()
{
throw myException();
}
inline void B::b2()
{
//code
}
}
Upvotes: 1
Reputation: 311038
In this point
class B; //declareation
//...
myException():std::exception
{
B::b2(); //error: incomplete type ‘A::B’ used in nested name specifier
}
the compiler does not know whether class B has member b2 because class B is not defined yet. So the compiler issues an error because it does not know what expression b2() means.
Also this statement
myException():std::exception
contains a syntaxical error. I think you mean
myException():std::exception()
You have to define the constructor after the definition of class B.
Upvotes: 0