Why class static member are considered declaration while instance member are not?

Viewed 68

Consider the following code as C++ Primer 5th Ed. section 7.6.

class Bar {
public:
    // ...
private:
    static Bar mem1; // ok: static member can have incomplete type --> Tag 1
    Bar *mem2;       // ok: pointer member can have incomplete type --> Tag 2
    Bar mem3;        // error: data members must have complete type --> Tag 3
    int x=4; --> Tag 4
}
  1. The above class definition considered to be a definition. This so call definition has NO STORAGE allocated like a created object.
  2. Tag 1 & 2 works because Bar are considered declaration. I am good with that since there's no object of class Bar created. These are declaration within the class definition.
  3. Tag 3 is where I have trouble with. To me tag 3 is considered declaration because no instance of class Bar is created yet.
  4. Tag 4 - I will also considered this a declaration at this stage since no instance of class Bar is created.

Point is those data members like tag 3 & 4, I would considered them as definition only if instance of class Bar is created outside of the class definition.

Bar bar; --> this would then initialize tag 3 & 4 --> Tag 5

Why is tag 3 needs to be complete as at this line there is no storage allocated since it's still a declaration? Tag 3 is not an instance yet at this line. Tag 3 only becomes a definition and have storage allocated when we create the class Bar outside of the class definition as in Tag 5.

1 Answers

Remember c++ class definitions define a memory layout. Unlike most higher level language there is no reference implied in the decoration of a variable is expressed as a litteral block of memory for that data in line in the continuous block of memory for that class or structure.

The declaration of an instance member variable of type Bar as a piece of Bar creates a unresolvible recursive definition because the memory of Bar contains as a piece all the memory of a Bar in addition to other stuff.

The static variable works because it does not have to be allocated in every instance of Bar just 1 for all instances of Bar to share and is more of a global variable associated with the namespace of the class and not a true member in the traditional sense.

The pointer works because a pointer simply refers to another piece of memory that should contain a Bar thus not running into the same recursive expansion problem when building the memory layout.

Related