Wednesday, July 8, 2009

Inheritance

A class defines a new type that extends the type system of the language. In languages like C++, a type is a skeleton for an area of memory containing values that follow a particular format. For instance, an integer may be 32 bits of binary number in the 2s complement format; a float may be 32 bits of binary number in the IEEE floating-point format. However, a type may also be seen as a model for a type of object found in the real world.
Things in the real world are classified into groupings called natural types. Each natural type has a number of attributes, called properties that are possessed by all the objects of that type. For instance, the class of all cats is a type with many properties, such as warm-blooded, four-legged, hairy and whiskered. All cats have these properties, and the presence of these properties distinguishes cats from, for instance, humans, which are warm-blooded and hairy, but only have two legs, and no whiskers. When we represent such classes using C++, we could duplicate the common properties like this:
class human { };
class cat { };However, we can leave the common properties in the human class, and allow the cat class to inherit these properties, avoiding the duplication:
class cat : public human { };Of course, we should also stop the inheritance of the property four-legged, and we can do that by over-riding a property with another of the same name. See C++ inheritance for the details.

Function scope

Braces also define the scope of a function's body. Variable names declared locally can be contained anywhere between the braces. One minor break in the rules is that any parameters declared in the function header are also considered to be inside the function's scope (whereas the function name itsef is not). e.g. in
int Function(int a, int b) { int c = a + b;}all the names a, b and c are considered local to the function. The name Function is non-local.

Function member definition

If a function member is not defined as inline, then it must be defined outside the class. This done by prefixing the function name with the class name and the scope-resolution operator, :: (colon-colon). This qualifies the name to avoid ambiguity when function names are reused in different classes. This appears to break the rules of scope, because references to variables declared within the scope of the class are allowed in function member definitions. The rules are merely being extended, however, if it is accepted that the definition of the function is "really" contained in the class, but is just placed externally for readability purposes. It also provides a declaration versus implementation view that abstract data typing demands. An exmple of external definition is:
class Ext {private: int privateVariable;public: void extFun(); ...};
void Ext::extFun() { privateVariable = 10; // reference to name in the class scope}

Function members

An object may contain functions which are stored internally and are unique to that object. Each such function needs an appropriate declaration, as a prototype, in the class.
Function members can be ordinary functions, but they can be overloaded, have default parameter values, or be virtual.
Special function members are constructors and the destructor. In the example below, there are two (overloaded) functions called f1, one private and one public; two constructors, one private and one public, and one destructor;
class C {private: void f1(int); C();public: void f1(int, int); C(int); ~C();};
Function members can be called using the same member access operator as data members.

Friend

Classes can also control access to their private members by using the friend declaration. There are two variations on this:
Access can be granted to individual member functions of another class by using the following form: friend return type X::f(param types...);
any number of functions can be granted access in this manner. Access can be granted to all the functions of a class by: friend class X;
The best way to think about friend functions is that although they are actually declared in another scope, the friend declaration "imports" them into the scope of the declaration, thus allowing direct access to private members.
Of course, since friend functions are not member functions access still has to be through an object of the class declaring the friend.
For example, the function FR in class B, below is granted access to the private member x of class A, but still has to use an object of type A to effect the access:
class A {private: int x;...friend void B::FR();};
class B {... void FR() { A a; cout << a.x; // direct access allowed by friend declaration }...};

File scope

File scope
Names declared outside any function or class have file scope, since their only boundary is the file in which the name occurs. The compiler can link the same name with file scope across files, or this can be prevented by using the keyword static. These names are typically called global.

Encapsulation

Variables in C++ are subject to two constraints. One is the rules of scope, and the other is access control. Encapsulation allows the programmer to control both the scope of names, and access to functions and/or values stored inside an object. The main construct is the class, which allows both variables and functions to be declared within it. These names are subject to visibility rules, and can be declared as having private, or public access.