Glossary and Tutorial for
Object Oriented Programming and C++
vers. 1.3
By: John Schwenk
Last modified: May 9, 1990
Introduction
This is a tutorial and glossary of terms related to Object Oriented Programming (OOP) and the C++ programming language originally intended as a companion to John Schwenk's "MacLunch" on the subject. The OOP terminology used is that of C++. C++ terms unrelated to OOP are also included.
This document can be used both as a reference and as a tutorial. To use it as a tutorial, I suggest that you read the following few entries in the order shown: C++, object oriented programming, object, class, directed acyclic graph, virtual function. You can then read the remaining entries in alphabetical order. After reading all of the listed entries (perhaps more than once), it is hoped that a broad understanding of OOP will emerge.
Glossary terms are listed in alphabetical order. Underlined words are C++ keywords. Glossary terms are emboldened the first time they appear in the text of another entry. Terms listed with an asterisk (*) are specific to Macintosh MPW C++.
I can't guarantee that this information is completely correct (but I've tried my best). Only a broad overview could be provided; the information is certainly not complete. Thanks go to Alan Talbot for elucidating errors in the manuscript and making valuable suggestions.
Glossary
Abstract class
A base class which is not intended to have objects made from it directly but rather only to be inherited by other classes. See directed acyclic graph.
Abstract data type
See User defined data type.
Base class
A C++ term for a class which is inherited by another class (called a derived class). The derived class inherits all member functions and member variables from the base class. A base class can be a derived class also (creating a hierarchy of classes).
In other languages this might be called a "superclass" or a "mixin flavor".
C++
A programming language designed by Bjarne Stroustrup at AT&T, in cooperation with Brian Kernighan and Dennis Ritchie, as a successor to the C programming language. C++ is a strict superset of C and is currently implemented as a preprocessor rather than a new compiler. The aim of C++ was to add a few features to C, and especially those necessary for object oriented programming techniques, without making the language significantly less efficient or more complicated.
Class
A type of object. An extension of the structure template which can include functions (member functions) as well as variables (member variables), has provisions for inheriting the functions and variables of other classes (inheritance), for limiting access to members in a useful way (data hiding), for having several versions of a function with the same name which are distinguished on the basis of the types they operate upon (overloading), and for redefining the actions of ordinary operators like + and == (operator overloading).
A class is very much like a structure template with a few key features added. Like a structure template, a class is a type or template. It is not itself a thing that code can operate upon. Objects of a particular class can be created by the compiler (stack based) or created dynamically at runtime (heap based). Many objects can be created of the same class just as many structures can be created of the same structure template.
A class can be thought of as a user defined data type because, like a structure template, it contains a template for the data contained within objects of the class, but it also contains a set of functions and operators which operate on that data. Like the built in data types (e.g., integer, float) a variable or variables holds the data and the compiler is given the methods to perform operations on that data (e.g., addition and subtraction).
In general, the member variables of an object are not directly accessible to the outside world. Interactions with an object come about through calls to it's member functions. This makes an object kind of a black box. You don't necessarily know what's inside it or how it works, but you do know that if you make a call to one of it's member functions that it will do a certain thing. Thus, an object has a state (the state of it's internal member variables) and a set of behaviors (or means of changing it's state) which are defined by it's member functions.
As an example, one of the C++ libraries contains the class "complex" which defines a complex number data type. The complex class definition specifies that each object of class complex will contain two float member variables, one for the real part and one for the imaginary part. It also specifies how complex addition, subtraction, etc. are performed. Whenever two objects of class complex are added the member function for addition, defined in the class complex, is called to perform it.
See also: object.
// Comment delimiter
In C++ the double backslash, //, delimits a comment to the end of the line. Example:
void dumb_func() // This is a C++ comment
The normal C comment delimiters, /* */, still work. The /* */ construct can enclose // comments. If // is used exclusively for normal comments, a /* */ can be placed around a section of code without causing the nested comments problem. This makes the task of commenting out sections of code much easier.
const keyword
Appearing before the type in a variable or parameter declaration, the const keyword specifies that the variable or parameter will not be changed after it's initialization. The compiler will flag an error at any attempt to do so. This is often useful in combination with a reference.
The const keyword is used in other situations not covered here such as with member functions.
Constructor
A C++ member function with the same name as that of the class which is used to initialize a new object of the class or perform side effects anciliary to the creation of the new object.
The compiler creates constructors if they are not defined by the user. In instances where how to construct an object is ambiguous, the user must define one or more constructor functions. There are different kinds of constructors for initializing, assigning, and coercing different types into an object.
Another name for construction is "instantiation".
Objects are disposed of and their heap space freed by destructors.
This is a very brief overview of constructors. Refer to the C++ documentation for more information.
Data abstraction
See user defined data type.
Data hiding
The act of making variables or data structures invisible or inaccessible to certain parts of a program. Data hiding is one aspect of modularization. Increased data hiding is one of the advantages of object oriented programming.
An ordinary example of data hiding is a local variable. A local variable is hidden from code outside the block in which it is defined. In the context of OOP and C++, private and protected members are hidden from code outside the object in which they exist; they cannot be accessed except by member functions and friend functions. Interaction with data contained within an object (member variables) should be performed only by the member functions whenever possible. That is, members should be made private and protected, rather than public, whenever possible. This makes an object a "black box" whose internal workings are unknown and whose interface is defined by the member functions. The data within the object is "encapsulated", or "hidden" from the rest of the program.
Data hiding makes large programming efforts easier by limiting the range of things of which the programmer needs to be conscious, eases code modification by insulating changes, and improves reliability by avoiding unintended interactions.
See also: Private, Protected, & Public keywords.
Declarations (in statements)
In C++, a declaration can occur at any place within a block, not only at the top of the block. This can done simply by preceding the first assignment or use of a new variable with it's type. This is convenient but some find it less readable.
Default parameter values
A C++ parameter which, if not passed in the function call, will be replaced by a default value provided in the source code. Example:
void func_with_default_param(int a, int b = 2) // b is optional
func_with_default_param(1, 3); // both params supplied; b<-3
func_with_default_param(1); // a<-1; b will get 2
delete operator
The C++ delete operator calls the C library function "free" to deallocate heap space previously allocated for a variable or array by the new operator. The advantage to using delete rather than free is that if we delete an object, the destructor function for that class (if it is defined) will be called automatically to finalize the object before it's space is freed.
The delete operator is the inverse of the new operator.
Derived class
A C++ term for a class which inherits from one or more other classes (called base classes).
The derived class inherits all of the member variables and member functions from its one or more base classes. A derived class can, in turn, be a base class of another derived class.
In some other languages, derived classes are known as "subclasses".
See also: base class, inheritance, multiple inheritance, directed acyclic graph.
Destructor
A C++ member function having the same name as it's class but preceded with a tilde (~) which destroys objects of its class for which there is no longer a use. The destructor performs whatever operations are necesary to dispose of objects no longer used, including deallocation of heap space for dynamically allocated objects, and any side effects which may be needed.
A destructor is provided automatically by the compiler if one is not defined. One would define a destructor if, for example, some side effect was required whever an object was destroyed, such as closing a serial port that the object was being used to represent.
Example:
class my_class_name { // A class declaration
// ...private members go here...
public:
// ...public members go here...
~my_class_name(); // The destructor, defined elsewhere
}
Directed acyclic graph (DAG)
A kind of topological map which can completely describe the inheritance structure of a set of classes with multiple inheritance. Often this is called a hierarchy but, technically, a hierarchy can describe a class structure with single inheritance only. DAGs and hierarchies can be thought of as "family trees" of classes, showing how members are inherited in a lineage from one class to the next. DAGs add "fan-in" to a hierarchical tree structure.
"Directed" refers to the fact that inheritance flows only in one direction down the graph. "Acyclic" means there are no loops; a class cannot inherit itself either directly or indirectly by inheriting some lineage of classes that eventually has itself as a base class.
Here is an example of a class structure, in the form of a DAG, that might exist inside an object oriented MacDraw style application:
Each of the names in the figure represents a class. The lines represent inheritance. Thus, the Shape class inherits from the Generic_graphic_object class. The Rectangle class inherits from both the Shape and Fillable_shape classes (this is multiple inheritance). The shaded classes are known as abstract classes; they are not intended to have objects made from them. They are intended as base classes only. Their purpose is to provide members to derived classes through inheritance which are common to all the derived classes.
The Generic_graphic_object class would contain those member functions and member variables that all objects displayed in the window would need. This might include member variables for the object's position and color and member functions for returning the position of, and moving, the object. These attributes are shared by all displayable objects including all shapes and text. This class might also contain virtual functions to create, draw, and rotate the graphic object. Virtual functions are member functions which derived classes need but which will be defined differently for different derived classes. For instance, drawing an object must be performed in a different manner when the object is a Text object or a Rectangle object (see below).
The Shape class inherits all members of Generic_graphic_object, and adds or redefines (overrides) members which may be unique to shapes (as opposed to text). The Rectangle class inherits all aspects of Shape and adds or redefines any members unique to rectangles, such as height and breadth. It will also define the virtual functions which were declared in the Generic_graphic_object class. The Rectangle class's draw() member function will be defined to draw rectangles using the position, color, height, and breadth member variables.
Note that the Rectangle class inherits from the Fillable_shape class in addition to the Shape class. Fillable_shape contains members which apply only to shapes that can be filled with a pattern, such as a variable for what pattern and a function for filling. Fillable_shape is another abstract class which is not intended to be constructed on its own but only to be inherited by other classes. When Rectangle inherits from both Shape and Fillable_shape it inherits all of the capabilities that pertain to each of those classes.
See also: class, inheritance, virtual function.
Friend functions and friend keyword
In C++, a friend of a class is a function that is not a member function of the class but which still has access to private and protected members of objects of the class. Ordinarily, private and protected members of a class are not accessible to any code outside the member functions of that class (and derived classes in the case of protected members). Friend functions are a way of short circuiting the data hiding feature of classes in the special cases where this is necessary.
A friend is made by declaring it with the friend keyword among the private members of a class. If a class is declared a friend, then all member functions of that class are friends.
Remember what a friend is by remembering that friends "share" things. In this case, classes share their members with non-member friend functions.
A general rule of thumb for OOP style can be stated like so: "Make few friends and keep as much private as possible."
Garbage collection
A background process provided with some object oriented programming environments in which storage associated with discarded objects (objects to which there are no longer any active pointers) is deallocated and reclaimed for use without the need for the programmer to do anything.
C++ does not do garbage collection. Instead, it is the responsibility of the programmer to manage the destruction of all his own objects.
See also: constructor, destructor, new, delete.
Handle-based class*
A special Macintosh C++ class in which objects are pointed to using handles rather than pointers. This allows use of the Memory Manager with the objects. A list of limitations accrue to handle-based objects (see the document, MPW C++ Language Extensions).
To create a handle-based class, make HandleObject the only base class. (Multiple inheritance is not allowed with handle-based classes.)
Hierarchy
1) A kind of topological map which describes the inheritance structure of a set of classes with single inheritance. 2) The set of classes represented by a map itself.
Often this term is used informally to refer to class inheritance structures with multiple inheritance but, strictly, such a structure is a directed acyclic graph. DAGs and hierarchies can be thought of as "family trees" of classes, showing how members are inherited in a lineage from one class to the next.
See also: directed acyclic graph.
Inheritance
An OOP concept whereby members of one class (called a base class) can be inherited by another class (called a derived class). It is as if the definitions of all the member functions and member variables of the base class were textually copied into the derived class. It has the advantages that the member function object code is not duplicated by the compiler and only one copy of source code needs to be maintained (all classes that inherit from the base class will receive the changes automatically). It also allows the implementation of polymorphism.
It is primarily the existence of inheritance that distinguishes a truly object oriented language from one that supports mere data abstraction.
See also: directed acyclic graph, user defined data type, polymorphism.
inherited keyword*
A Macintosh specific C++ keyword which provides a mechanism for refering to a member function of a base class that has been overridden in the derived class. This is an alternative to using the name of the base with the function name. For example:
inherited::function_name
refers to the function which would have been found if function_name had not been redefined in the derived class. That is, the member function which would have been inherited had it not been overridden by a new definition.
inline function and keyword
If the C++ keyword "inline" appears before the function name in a function definition, the compiler attempts to substitute the function's code inline, like a macro, thereby avoiding the function call overhead. Inline functions are unlike #defines, however, in that scope rules apply and argument type checking is performed.
Typically only very short functions are made inline. Certain types of functions cannot be made inline (see the AT&T C++ Reference Manual). If a function is defined within the scope of a class definition, it is automatically made inline (if possible).
Instance
Another word for object. The phrase "instance of a class", refers to an object of a particular class. The process of creating an instance/object is often called "instantiation". C++ also uses the term "construction" for this process.
Member
An element of a C structure or C++ class. Members can be objects of any type including user defined as well as language defined types. Members which are functions are called member functions. Members which are variables are called member variables.
All members of a base class are inherited by all classes which are derived from the base class (called derived classes).
Members of a class can be private, protected, or public. These three kinds of members differ in their degrees of visibility to the rest of the program.
Member function
A C++ function which is a member of a class or object. A member function is called with the same syntax with which a member variable of a structure is accessed - using a "." (dot) construct like so:
object_name.member_func_name(); // Calls member func of object
Ideally, member functions represent the interface to the outside world of an object. These functions represent the repertoire of behaviors available to the object. Member functions usually use or operate on the member variables of an object and thus change the "state" of the object.
Member functions are called "methods" in some other object oriented languages. The process of calling them is sometimes refered to as "message passing" to emphasis the intended modular nature of objects.
Member variable
A C++ variable which is a member of a class or object. A member variable of a class or object is much like a member of a structure and is accessed using the very same dot or -> notation. Member variables represent the "state" of an object.
Member variables are called "instance variables" in some other object oriented languages.
Multiple inheritance
An OOP facility which allows a derived class the ability to have more than one base class. In this case, the derived class inherits all the member functions and member variables of all of the base classes.
(Multiple inheritance is a new feature in release 2.0 of C++. Previously only single inheritance was allowed; classes could inherit from only one other class. Object Pascal and MacApp do not allow multiple inheritance.)
new operator
Like the library functions malloc() and calloc(), the C++ new operator is used to allocate heap space for new objects, structures, arrays, or variables at runtime. The advantages of using the new operator over malloc() or calloc() are that a pointer of the proper type is returned (no need to cast it into a pointer to an object of the right type) and that, if a constructor is defined for the class from which an object is being created, it will be called automatically to initialize the newly allocated object.
The delete operator is the inverse of new and is used to dispose of objects that are no longer needed and thereby reclaim their heap space.
Object
A bundled collection of variables, and logically related functions that operate on or with the variables, that may be regarded in some sense as a discrete "thing" or model of a thing. An object is similar to a structure except that it almost always has member functions and adds several important features such as inheritance, data hiding, and overloading.
As an example, an object might be used to represent a window in a windowing system. Variables in the window object might hold the window's position, size, and state; whether the window is active or inactive, frontmost or hidden. Other variables might hold text or other objects displayed in the window. Functions associated with the window object might be used to draw, draw contents, grow, open, close, reposition, activate, or zoom the window.
Another example would be to use objects to represent individual shapes in a MacDraw type application. The object's variables would be used to hold the position, size, color, and other aspects of the shape. The functions would plot, erase, and allow the user to draw the shape with the mouse. Note that our window object might contain an array of pointers to shape objects that are displayed in the window.
Every object has an associated type or class. An object is to a class as a structure is to a structure template. There can be many objects of the same class just as there can be many instances of a structure derived from the same structure template. The class itself is not a real "thing" that code can act upon. Just like a structure template, it is merely a description from which objects can be made.
Objects can be created statically by the compiler (stack based) or created and destroyed dynamically at runtime (heap based) in processes called "construction" and "destruction" in C++. (See constructor and destructor).
Another name for an object is an "instance" or an "instance of a class".
Object Oriented Programming (OOP)
A programming paradigm (like "structured programming") that came into vogue in the '80s. The core concept of OOP is the "object", which consists of a data structure (collection of variables) and a set of functions which use or operate on that data structure. A template for, or type of, an object is called a "class". Objects of a particular class can be created statically by the compiler or dynamically at runtime as needed.
Objects "encapsulate" the data structure internal to them. Ideally, the data structure within an object is "hidden" from code outside that object and all interaction with the data occurs through calls to the functions associated with the object (see data hiding). Thus, the data structure represents the "state" of the object and the functions represent the objects repertoire of "behaviors". Objects represent a new way of modularizing code, and all of the associated advantages accrue.
A class, or type of object, can be regarded as a new, user defined, data type just like a float or an int. Like floats and ints, an object of a class has associated with it some storage and a set of operations that can be performed using that storage (like +, -, etc.).
The concepts that we have so far discussed can be placed under the heading of "data abstraction", "abstract data types", or "user defined data types". Another concept key to OOP is that of inheritance. With inheritance, classes can be built upon one another to form a tree structure representing their lineage or family tree. When one class "inherits" from another class, it inherits all of that class's variables and functions. The new class may add new variables and/or functions to tailor it to a somewhat different use. Inherited functions that are not suitable to the new task can be redefined for the new class and thereby overridden. Inheritance facilitates the reuse of code.
The concept of a class can be regarded as an extension to the concept of a structure template. A class is like a structure template except that it almost always has member functions and adds several important features such as inheritance, data hiding, and operator overloading.
Adding functions to structures yields what is refered to as "data abstraction" or user defined data types. Combining data abstraction with data hiding, operator overloading, and inheritance is generally regarded as sufficient for a true object oriented programming language.
See also: user defined data type, class, object, inheritance, reuse, data hiding, virtual function.
operator overloading
The ability, in a C++ class, to redefine the standard operators such as +, &&, <<, !=, etc.. (See overloading). A member function is defined by the programmer to take over the function of the operator being overloaded. Any use of the overloaded operator with objects of that class will utilize the class's member function for that operator.
Operator overloading is performed by declaring a special member function with the name "operatorX", where X is the actual symbol of the operator to be overloaded. In this example, the operator == is being overloaded to compare instances of my_class instead of the usual built in types (e.g., ints, floats):
boolean my_class::operator== (const my_class& an_object) {
// Code here compares two objects of class my_class,
// in whatever way this may be meaningful for this class,
// and returns a boolean as a result.
}
(Note that this definition uses the scope resolution operator, ::, the const keyword, and a reference: my_class& an_object.)
Note that most operators are already overloaded by the compiler. Integer addition is performed in a different manner than floating point addition. The programmer, however, doesn't need to know this; he simply uses the the + operator blindly. The ability to overload operators allows the programmer to extend this same ability to objects of his own classes. Having overloaded the == operator for the class my_class, any use of == with objects of my_class will automatically invoke our function. == will continue to work as before with all other types. The compiler senses which == function to invoke based on the type of the variables being used with the operator.
The use of operator overloading can simplify the tasks of reading and writing programs.
Operator overloading is a special case of overloading generally.
Overloading
A C++ provision whereby member functions of the same name can be defined to operate on different types or numbers of parameters. The compiler will choose the function to use that is appropriate to the types or number of the parameters passed. Do not confuse overloading with overriding.
Note that the ordinary numerical operators, such as +, are already overloaded by the compiler. + will do different things depending on whether two ints, two floats, or an int and a float are being added. Essentially, there is a set of + functions, one for each combination of types for which + can be used. This fact, however, is transparent to the programmer. If + did not have this feature, you would have to choose from among a set of differently named + functions appropriate to the types of the operands (e.g., floatfloat+, intfloat+, intdouble+, etc.). The overloading feature of C++ extends to the programmer's own member functions and types (classes) this same "aliasing" ability that the compiler has always had for it's own operators and types.
Overloading is performed simply by having multiple declarations and definitions of member functions of the same name but with different types of parameters, a different number of parameters, or both. The compiler will distinguish among them and choose the one appropriate to the parameters passed in a call.
See operator overloading for a special example of overloading.
Overriding
In a derived class, the ability to replace, with a new member function, a member function that would have been inherited from a base class. See Inheritance.
Overriding is an aspect of a process of incremental refinement in the development of a class hierarchy. Incremental refinement is a process whereby derived classes become more specialized versions of the same general type.
Typically, a base class contains elements which are common to all classes derived from it. As derived classes are created, more elements (member functions and member variables) are added to complement the inherited ones in order to create a more specialized class. The implementation of some of the inherited member functions may not be suited to the derived class. These functions would be overridden in the definition of the derived class. A new function would be written to replace the inherited one. The new function has the same name as, and an analogous purpose to, the one being overridden.
The new function may call the inherited function by refering to it explicitly (see scope resolution operator, and inherited keyword). In this way, the new function may simply add to or redo some things that the inherited function already does.
Do not confuse overriding with overloading.
Polymorphism
The ability, in an object oriented programming system, for the same name to refer to different member functions depending on the class of the object for which the function was called. This allows code to deal with objects in a generic way, without needing to know the precise types (classes) of the objects.
See virtual function and keyword for more information.
private, protected, & public keywords
These C++ keywords are used within a class definition to control what sections of a program have access to the class members (vars and funcs). All three kinds of members may exist within one class.
Private members can be accessed only by member functions within the particular class (or functions which are friends of the class). Except in the case of friends, private members are hidden from code outside that of the class itself; no access to private member variables or member functions will be allowed except to other member functions.
Protected members are similar to private members except that access is granted to member functions of all derived classes as well as member functions of the current class.
Public members can be accessed from any part of a program whether part of the current class or not. Public members constitute the interface between objects and the outside world. Note that all members of structures are "public".
Private and protected class members are one way that C++ OOP achieves data hiding. It is good programming practice to make members as private as possible. That is, only the degree of exposure to the outside that is absolutely required of a member should be granted to it. Furthermore, you should structure your classes in such a way as to maximize this data hiding. Objects should be like black boxes; there's no need to know what's inside or how it does what it does. All the user of the object/black box needs to know is its interface, which has been carefully designed to shield him from as much implementation detail as possible. (See data hiding.)
Another aspect of this is that all member variables should be private (or protected). Only member functions of the class (and friend functions) should operate on the member variables. "Accessing" member functions should be written to set and return the value of each member variable for which this is necesary. In this way, implementation details internal to the class are shielded from the rest of the program. Changes can then be made to the representation or implementation within the object without requiring modification of anything else. As a trivial example, a member variable could be changed from int to float without having to search the entire source code and modify all places where the variable is accessed. One would merely change the variable's accessing member functions.
A general rule of thumb for OOP style can be stated like so: "Make few friends and keep as much private as possible."
Reference
A C++ construct which allows an argument to be passed by reference where C would ordinarily perform a pass by value. In C, all arguments are passed by value except arrays which are passed by reference. You can get around this by passing a pointer to the variable instead, but this can be a pain. C++ nicely provides a means of passing variables by reference.
A reference is declared in a parameter list by placing an ampersand (&) to the right of the type name of the parameter. The parameter's name can be used in the function without modification and now refers to the variable itself rather than a copy of the variable. This is same as using the VAR keyword in Pascal. Here is an example:
void my_func(int& b) // b is a reference to the int passed in
{
b++; // the passed var itself, not a copy, is incremented
}
int c = 1;
my_func(c);
// c now equals 2
// if a reference was not used, c would still be 1
References can also be used to avoid the runtime overhead of copying variables during calls. In this case the intention may not be to change the value of parameter within the body of the function but rather to avoid changing it. We can use the const keyword in combination with the reference to prevent any tampering with the parameter by the function. If the keyword "const" is placed before the "int&" in the function definition above, the "b++" will be flagged as an error by the compiler since it is an attempt to change a const. (See const keyword.)
Reuse
One of the advantages of OOP is its ability to facilitate reuse of code.
One way this is done is through the mechanism of inheritance. A derived class can reuse the member functions and member variables inherited from its base class(es). It need only define any new features that it needs and redefine any others which need to be changed for the new class.
Another way that OOP facilitates reuse is that, once defined, classes can be regarded as a library of resources ready to be drawn from. Someone else may have defined a class which you can use, either directly, or indirectly by deriving your own class from it and modifying its members as required. Creating your own objects from someone else's classes will never interfere with the operation of preexisting objects or code. In contrast, one must carefully craft ordinary functions so that they will be generic enough to meet someone else's needs and so that outside calls to that function don't interact with any other uses of the function.
C++ provides several class libraries just as C provides function libraries.
:: Scope resolution operator
In C++, if a name has been defined in both global and local contexts, preceding an instance of the name with a double colon will always make it refer to the global version. Here's an example:
main() {
int i = 1; // a globally defined i
{ // new block
int i = 2; // another i defined within this block
(i == 2); // returns TRUE (local i)
(::i == 1); // also returns TRUE (global i)
}
}
Another use of the double colon operator is to separate a class name and a member name in the otherwise ambiguous case where there is a member of the same name in more than one class. For example, if class_a and class_b are classes which both have a member named x, then:
class_a::x // refers to member x of class_a
class_b::x // refers to member x of class_b
This construct is typically used in the definition of member functions. The member functions have already been declared in the class definition. Since there may be more than one class which has declared a member with the same name, we must use this construct in our function definitions to avoid ambiguity.
static member variable
A member variable of which only one copy exists for all objects of a given class. A member variable which is declared as static (preceded by the static keyword) within a class definition is not seperately created for each object that is constructed of the class. Only one static member variable is created for the entire class, regardless of how many objects are created of the class. A reference made to the member variable, be it through any object of the class, will refer to the very same variable.
A static member variable can be thought of as a global variable whose scope is limited to member functions of objects of a particular class.
Note that this is yet another distinct use of the abused C keyword "static".
this keyword
When used within a member function, the C++ keyword "this" is a pointer to the object for which the member function was called. This pointer is automatically defined for you by the compiler. This is useful when it is necessary for a member function to use a pointer to the object for which it was called.
Object Pascal uses the keyword "self" for the same purpose.
User defined data type or abstract data type
A data type (like float) that is user, rather than language, defined. As with language defined types, instances of a user defined type have associated storage and operators that function with the type. A structure that includes member functions that use or operate upon the other members of the structure may be regarded as an abstract data type. A user defined or abstract data type may also have operator overloading.
An abstract data type is a subset of a class. It has all the features of a class except inheritance and virtual functions. It is the existence of these last two features that separate languages that support abstract data types and ones that are truly object oriented.
virtual function and keyword
A C++ member function that has its calling interface defined in a base class (using the "virtual" keyword) but the function body redefined (overridden) in one or more derived classes. This provides a mechanism to support polymorphism, the ability for a single function name to refer to different member functions depending on the class of the object for which the member function was called.
A pointer to an instance of the base class can also point to instances of any class derived from the base class. If a virtual member function has been declared in the base class and that function is called through the pointer to a derived class, the function that corresponds to the particular derived class will be called. That is, the selection of the function appropriate to the particular derived type will occur automatically.
This automatic selection of the member function appropriate to a particular class is a powerful feature that allows code to be written in a generic way; without regard to the exact type of object being manipulated. Knowledge of the particular (derived) class of an object being manipulated need not be known at compile time. There would be no need for a case statement to select between different functions based on the type of object being manipulated.
As an example, consider an object oriented MacDraw-type application. Let's define a base class called "shape" which will contain members that are common to all different kinds of shapes including circles, lines, etc.:
class shape {
private:
point pos; // position and color are common
color shape_color; // to all shapes
public:
point shape_position(); // returns shape's position
void move(point to_position) // moves the shape on the screen
virtual void draw(); // draws the shape on the screen
virtual void rotate(float deg);// rotates object by deg degrees
virtual void create(); // allows user to mouse a new one
};
Note that the first two member functions are not virtual. That is because they can be the same for all kinds of shape; they don't do shape specific things. They will be defined once somewhere else in the source.
The last three member functions have been declared using the virtual keyword. This means that they will not be defined for this class but rather for classes derived from this class. These functions must perform their functions in different ways depending on the particular shape for which they are called (e.g., a line is drawn in a different manner from a circle).
Let's define one particular shape:
class line : public shape { // line inherits from shape
private:
point far_end; // the inherited "pos" is used as "near" end
public:
void draw(); // we'll define these funcs for lines below
void rotate(float deg);
void create();
};
Here is one of the virtual member functions defined for the line class:
void line::draw() // Draws line objects on the screen
{
// Does Mac specific stuff to plot the line from
// center to far_end on the screen
// ...
}
Given a set of draw functions, one for each kind of shape derived from the shape class, we can now draw all the shapes we may have on our screen.
(Our shapes are held in an array of pointers to shape objects. The parameter last_shape holds the index of the last shape in the array.):
// Draws the entire picture on the screen
void draw_all_shapes(shape* shape_array[], int last_shape)
{
for (int i = 0; i < last_shape; i++) // for all shapes
shape_array[i]->draw(); // draw each one
}
Note that this function does not need to know the particular kinds of shapes that it is drawing, even though each kind gets drawn in a completely different manner. It simply calls the function draw(), which is virtual in the shape base class, and the action appropriate to the class of the object takes place. In a system without polymorphism, a case statement would be required to determine the type of the object, then functions of different names would have to be called, one for each type (e.g., draw_line(), draw_circle(), etc.).
See also: directed acyclic graph, overriding, polymorphism.