John
John

Reputation: 67

Incomplete type used in nested name specifier

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

Answers (3)

Mike Seymour
Mike Seymour

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

R Sahu
R Sahu

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

Vlad from Moscow
Vlad from Moscow

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

Related Questions