Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can a class be used within itself in member function definition, but is regarded as incomplete when used as a member?

Tags:

c++

types

class A
{
     private:
        A a;
};

Why is the A in class an incomplete type?

class A
{
     public:
          A& operator= (A a){return *this;}
};

Is not the parameter A of operator= an incomplete type? Why does the code above compile?

like image 433
binbin Avatar asked Sep 28 '22 10:09

binbin


2 Answers

Because there is a difference between using A in open space in the class definition, and using it in the parameter-list of a member function definition. Those are two different scopes.

[C++11: 9.2/2]: A class is considered a completely-defined object type (3.9) (or complete type) at the closing } of the class-specifier. Within the class member-specification, the class is regarded as complete within function bodies, default arguments, exception-specifications, and brace-or-equal-initializers for non-static data members (including such things in nested classes). Otherwise it is regarded as incomplete within its own class member-specification.

And then the following special case:

[C++11: 8.3.5/9]: Types shall not be defined in return or parameter types. The type of a parameter or the return type for a function definition shall not be an incomplete class type (possibly cv-qualified) unless the function definition is nested within the member-specification for that class (including definitions in nested classes defined within the class).

"That's just the way it is."

Speaking practically, it's clear that it would be impossible to store an A within an A (because that would require infinite encapsulation), whereas this is obviously not the case in a member function's parameter list. So the standard committee had the opportunity to make this a little easier for us, and they took it.

Furthermore, if you were to try to use a member of a inside the function's definition, then that is also allowed (per the first quote above), as if the function had been declared lexically after the end of the class definition.

like image 123
Lightness Races in Orbit Avatar answered Oct 05 '22 06:10

Lightness Races in Orbit


The first block is an impossibility in the general case, as to know what sizeof(A) (for the class) is it needs to know what sizeof(A) is (for the member).

The second case is different in that even if the definition of the member function is syntactically inside the class, the language considers the definition to be outside of the class. The compiler will translate that code as if you had typed it like:

class A {
public:
   A& operator=(A a);
};
inline A& A::operator=(A a) { return *this; }

Declaring a function taking or returning an object of incomplete type is legal. When the type is really used, inside the function definition outside of the class, the type is already complete, so it is perfectly fine too.

like image 28
David Rodríguez - dribeas Avatar answered Oct 05 '22 08:10

David Rodríguez - dribeas