C++ Builder Tutorials

C++ Tutorial: OOP in C++

In Object Oriented Programming (OOP), you write programs that manipulate objects.

An object is a combination of data and program code; it is created from a class (a kind of template, blueprint).

You could think of "TApple" as a class and a particular Apple as an object, an instance of the class "TApple".

The VCL (Visual Component Library) is a collection of pre-defined classes for creating objects such as forms, labels, panels, radio buttons, check boxes, etc.

Object and Class

An object is an "instance" of a class.
Instance means: a particular occurrence (case, specimen, example, sample) of something. In OOP, instance is synonymous with "object".

Objects have properties and methods.

A property returns an attribute of an object. Under the hood, a property is in fact a subroutine that gets or sets a hidden "field" of the object, but you can work with a property just as with a normal variable. Examples:

int W;
W = Panel1->Width;
Form1->Caption = 'The width of the panel is ' + IntToStr(W);
A property can return a number or a string, but a property can be an object as well, for example: Form1.Canvas

A method is a subroutine that acts on an object, such as:
Form1->Show();
Label1->Hide();
The creation of an object is called instantiation. Instantiation is also known as "construction".

The VCL components that you set up in the form designer, such as the forms, buttons etc are all "owned" by a global component called "Application". At the start of an application, "Application" automatically creates all of these components, and when it shuts down, it automatically destroys these components.
Important:
Each object that was created, must be destroyed before the end of the program.
VCL components that were created by "Application" will be destroyed automatically, but if you created an object yourself in your code, you have to destroy ("free") it explicitly.

OOP principles

Object Oriented Programming is based on the following principles:

  • Abstraction: only relevant stuff is shown, the unnecessary details are hidden.
  • Encapsulation keeps the internal data safe from external manipulation. The programmer only knows how to use an object, but the implementation is hidden (like how and where the data are actually stored).
  • Inheritance: each class inherits internal fields, properties and methods from another class, its "ancestor".
    This is specified in the "type declaration" of a class, such as this one that you see in a form's unit:
    type TForm1 = class(TForm)
    ...meaning: the class TForm1 inherits all from the class TForm that was predefined in the VCL, except for the properties that you customize, such as maybe its Caption, Color, Height, Width,...
  • Polymorphism: objects of different types can be accessed through the same interface. Different objects can respond to identical messages, each in its own way.
    For example, Form1->Show() and ListBox1->Show() both display an object on the screen, but the underlying code is very different.
    Encapsulation ensures that you don't have to worry how the method Show() was coded

Hierarchy of classes


Simplified family tree

TObject is the ultimate ancestor of all classes.

TObject encapsulates fundamental behavior common to all objects, by introducing methods that create, maintain, and destroy instances of objects, and support message handling.
If the declaration of a class type does not specify an ancestor, the class inherits directly from TObject.

TPersistent is the ancestor for classes that have streaming capabilities, meaning that they can read and write their properties to and from a form file (.dfm file).

TComponent is the ancestor of the component classes.

A component is a persistent object that can appear on the IDE palette and that can be manipulated in the Form Designer. A component can "own" other components. If the form Form1 owns Panel1, then Form1 is responsible for destroying Panel1 when Form1 is destroyed.

Components that can be visible at run time are sometimes called visual components. Other components, which are never visible at run time, are sometimes called non-visual components (such as TTimer).

TControl is for components that are visible at run time.

A control is a visual component, meaning that at run time, you can see it and possibly interact with it. All controls have properties, methods, and events that describe their appearance, such as their position (Left, Top), dimensions (Height, Width), methods to paint or move the control, and events that respond to user actions (such as clicking the mouse or pressing a keyboard key).

TWinControl is the ancestor for controls that are wrappers for MS Windows screen objects ("windows").

A WinControl has a "window handle", such as TEdit, TListBox and TButton. A WinControl can receive user input focus, either by clicking on it, by using the TAB / SHIFT TAB key, or under program control with SetFocus (for example: Button1.Setfocus).
Note: button components typically indicate the focus by drawing a rectangle around their caption.

A WinControl can serve as a container ("parent") for other controls, referred to as "child controls". Examples of container controls are: forms, panels, and toolbars.
Note that "parent" does NOT mean the same as "ancestor"!

TScrollingWinControl is for wincontrols that support scrolling.

A scrolling windowed control can display horizontal and vertical scroll bars, and it scrolls a child control into view when the child control receives focus.
Example of a scrolling windowed control: TForm

TCustomControl is for windowed components that provide their own custom painting.

In contrast, the controls which descend from TWinControl like TEdit and TListbox, already have default drawing capabilities, provided by the encapsulated MS Windows control.

TGraphicControl is for controls which are not windowed controls.

GraphicControls have no window handle. Also, they cannot be parents to other controls.

See also:

  Components