Object-oriented design with C++

In addition to general object-oriented principles, the Taligent Application Environment implements several design principles specific to C++.

C++ doesn't express full object interface

Although the strong typing features of C++ are a great help in defining the interface to a class, the entire definition of a class can't be expressed in the C++ class definition. The following important aspects (among others) of a class interface can't be adequately expressed in C++:

Class semantics--Not all of the semantic constraints on an object can be expressed through the C++ type system.

Concurrency--The behavior of an object in the presence of multiple threads of execution can't be expressed in C++.

Storage management--If an object has specific storage management semantics, they can't be expressed through the class definition.

Special conventions can help to document all these facets of a class in the class definition, but the compiler certainly can't use that information to check your code. Many semantic constraints can only be expressed in human language.

C++ requires definition of special member functions

For a class definition to be complete, you must define its constructor(s) and destructor, copy constructor, and assignment operators. If you don't define these special members, the compiler will, and it can generate them as inlines (which you want to avoid) or make incorrect assumptions about your class structure. If you don't want to allow clients to assign your class or return it from functions, make the copy constructor and assignment operators private with no implementation; this keeps the compiler from generating them for you.

Constructors and destructor--Every class should have a destructor and at least one constructor, even if they do nothing or are defined to do nothing. Be explicit; do not leave this up to the compiler.

Copy constructor--The copy constructor for TFoo is of the form TFoo(const TFoo&) or TFoo(TFoo&). This constructor defines the behavior of your class when it is passed by value as an argument, returned by value from a function, or used to initialize one instance with the value of another. You must define this constructor so that your objects are copied properly; otherwise, the compiler generates a default inline version for you.

Assignment operator--The assignment operator (operator=) is called when one instance of your class is assigned to another; if you don't define it, the compiler generates a default inline version for you. If you allocate subsidiary data structures on the heap or consume any other kind of shared resource, you need to define an assignment operator and a copy constructor. The compiler doesn't define assignment operators if you declare an assignment operator with argument type of TFoo, TFoo&, or const TFoo&.

If you let the compiler generate your copy constructor or assignment operator, at least insert a commented declaration:

// TFoo& operator=(const TFoo&); // Use default version.

Also remember that this constitutes an inline declaration; therefore, if you ever want to allow for a nondefault implementation, you must define these special members explicitly. See "Inline functions" on page 62.

Streaming operators--Although streaming operators (operator<<= and operator>>=) are not special members in the C++ sense, many of the same considerations apply. The compiler does not generate them for you, but the base class' operators will be inherited (if your base class has them) and might not do the right thing.

[Contents] [Previous] [Next]
Click the icon to mail questions or corrections about this material to Taligent personnel.
Copyright©1995 Taligent,Inc. All rights reserved.

Generated with WebMaker