Clarify this for me

Here's a snippet from my book:

Forward declarations: The requirement to define names before using them (§0.8/6) causes
trouble in writing families of classes that refer to one another. To avoid this trouble, you can
declare just the name of the class by writing
class class-name;
thereby saying that class-name names a class, but not describing the class itself.
We used such a forward declaration for class Picture in §15.2.7/286. The Picture class
contains a member of type Ptr<Pic_base>, and the Pic_base class has a friend declaration
for operator<< that uses the type const Picture&. Therefore, these two classes refer to each
other.
Such mutual type dependencies can yield programs that are impossible to implement. For
example:
class Yang; // forward declaration
class Yin { Yang y; };
class Yang {
Yin y;
};
Here, we have said that every Yin object contains a Yang object, which contains a Yin object,
and so on. Implementing such types would require infinite memory.
The mutual dependency in our picture classes does not cause such problems, because class
Picture does not contain a member of type Pic_base directly. Instead, it has a member of
type Ptr<Pic_base>, which contains a Pic_base*. Using pointers in this way avoids infinitely
nested objects.
Moreover, in the case of a pointer (or reference), the compiler does not actually need to know
the details of the type until operations are invoked through the pointer (or reference). Because
the declaration of operator<< uses the const Picture& type only to declare a parameter type,
the compiler needs to know only that the name Picture names a type. The details of that type
aren't needed until we define operator<<.


Can someone give me some examples of the whole infinite memory thing and also explain why it is avoided with a pointer/reference?
Last edited on
Let's take that code:

1
2
3
class Yang;
class Yin { Yang y; };
class Yang { Yin y; };


Provided that Yin contains within itself a Yang class and Yang contains in itself a Yin class, a Yang is supposed to look like this:

1
2
3
4
5
6
7
Yang{
   Yin{
      Yang{
         Yin{
         Yang{
            Yin{
            ...
which goes to infinity.

But when you include a pointer, you only include the address of whatever it points to, which is a 4-byte number, just like any integer. When the compiler meets a pointer, it doesn't replace it with the content of whatever is pointed, but it leaves it as an address.
Let's imagine that we have this code:

1
2
3
class Yang;
class Yin { Yang* y; };
class Yang { Yin* y; };


...and we create a Yang class called MyYang, and a Yin class called MyYin. Assuming MyYang in computer memory takes some space starting from 15200 (this is just in theory) and MyYin occupies the space starting from 15204, the data stored in MyYin and MyYang will be simply 15200 and 15204 respectively, which are only the locations of MyYang and MyYin. And whenever the compiler meets anything like:
MyYin.Yang->something
it only refers to Yang as: "Do *something* with the class whose address is 15200"


I apologise if this isn't clear enough.
Last edited on
Topic archived. No new replies allowed.