Every class defines a unique type. Two different classes define two different types even if they define the same members. For example:
Exercise 7.27: Add the move
, set
, and display
operations to your version of Screen
. Test your class by executing the following code:
Screen myScreen(5, 5, 'X'),
myScreen.move(4,0).set('#').display(cout);
cout << "
";
myScreen.display(cout);
cout << "
";
Exercise 7.28: What would happen in the previous exercise if the return type of move
, set
, and display
was Screen
rather than Screen&?
Exercise 7.29: Revise your Screen
class so that move
, set
, and display
functions return Screen
and check your prediction from the previous exercise.
Exercise 7.30: It is legal but redundant to refer to members through the this
pointer. Discuss the pros and cons of explicitly using the this
pointer to access members.
struct First {
int memi;
int getMem();
};
struct Second {
int memi;
int getMem();
};
First obj1;
Second obj2 = obj1; // error: obj1 and obj2 have different types
Even if two classes have exactly the same member list, they are different types. The members of each class are distinct from the members of any other class (or any other scope).
We can refer to a class type directly, by using the class name as a type name. Alternatively, we can use the class name following the keyword class
or struct
:
Sales_data item1; // default-initialized object of type Sales_data
class Sales_data item1; // equivalent declaration
Both methods of referring to a class type are equivalent. The second method is inherited from C and is also valid in C++.
Just as we can declare a function apart from its definition (§ 6.1.2, p. 206), we can also declare a class without defining it:
class Screen; // declaration of the Screen class
This declaration, sometimes referred to as a forward declaration, introduces the name Screen
into the program and indicates that Screen
refers to a class type. After a declaration and before a definition is seen, the type Screen
is an incomplete type—it’s known that Screen
is a class type but not known what members that type contains.
We can use an incomplete type in only limited ways: We can define pointers or references to such types, and we can declare (but not define) functions that use an incomplete type as a parameter or return type.
A class must be defined—not just declared—before we can write code that creates objects of that type. Otherwise, the compiler does not know how much storage such objects need. Similarly, the class must be defined before a reference or pointer is used to access a member of the type. After all, if the class has not been defined, the compiler can’t know what members the class has.
With one exception that we’ll describe in § 7.6 (p. 300), data members can be specified to be of a class type only if the class has been defined. The type must be complete because the compiler needs to know how much storage the data member requires. Because a class is not defined until its class body is complete, a class cannot have data members of its own type. However, a class is considered declared (but not yet defined) as soon as its class name has been seen. Therefore, a class can have data members that are pointers or references to its own type:
class Link_screen {
Screen window;
Link_screen *next;
Link_screen *prev;
};