Home : Summary of the C++ language
Variables can be declared anywhere in the code, not just at the start of a block. Their scope is up until the end of the enclosing block. If a variable is declared (for example) in a for statement, as in:
then the declaration is outside the braces, so i
remains defined after the end of the loop.
When a new structure (etc.) variable is declared, it no longer needs the
struct
(etc.) keyword before the structure name.
By using the scope resolution operator, a file level variable can be referenced even if a variable of the same name has been declared locally.
VarName |
accesses the local variable |
::VarName |
accesses the global variable |
The new
operator allocates a memory heap block large enough to hold
type, and returns a pointer to it.
Note the slightly different syntax for arrays:
Multiple functions can be defined with the same name, providing they have different numbers of parameters, or at least one parameter has a different type.
module.h | module.cpp | usercode.cpp | ||
short Func(short A); short Func(short A, short B); long Func(long A); |
short Func(short A); { } short Func(short A, short B); { } long Func(long A); { } |
X = Func(Y); The compiler calls the appropriate function based on the type of Y. |
Default values can be declared for function parameters, allowing them to be omitted when the function is called.
module.h |
module.cpp |
usercode.cpp |
||
int Func(int A, int B =
0); |
int Func(int A, int B); { } |
X = Func(Y); is exactly equivalent to: X = Func(Y, 0); |
These are very similar to pointer variables:
Reference variable: |
Pointer variable: |
|
type& RefVar =
Var; RefVar = expression; |
type* pPtrVar =
&Var; *pPtrVar = expression; |
All uses of RefVar
are exactly equivalent to using Var
; RefVar
is effectively an alias for Var
. Unlike a pointer, RefVar
cannot be reassigned to refer to another variable.
Reference variables are most useful as the parameters or return value of a function.
module.h |
module.cpp |
usercode.cpp |
||
void Func1(int&
A); int& Func2(void); |
void Func1(int& A) { A =
0; }return; int& Func2(void) { return B; } |
Func1(X); Results in X being set to zero. Func2() = 0; Results in B being set to zero. |
A class
encapsulates data variables and code functions into one object.
The data and functions are called members of that class.
The format of a class
is similar to a struct
; a struct
can be used like a class
whose elements (members) are all public
. A class object may be passed to or returned by a function using
exactly the same syntax as for a structure.
module.h |
module.cpp |
usercode.cpp |
||
Declaration class CName { public|protected|private: };type m_Var; type Func1(parameters); type Func2(parameters) { In-line function
code. } |
Implementation type
CName::Func1(parameters) { all member data and functions (whether
public, protected, or private) can be directly referenced as:
} m_Var or, more explicitly, as:
FuncN(parameters) this->m_Var this->FuncN(parameters) |
Instance CName
nameObject; nameObject.m_Var Accesses a public variable within the class. nameObject.Func(parameters) Calls a public function within the class. |
Within a class function, the this
keyword is a pointer to the current instance of this class. Its
effectively an additional parameter to the function.
Note the convention is to prefix the name of a class with an uppercase
C
, and to prefix the name of any member variables with a m_
.
If a class CName
declares a function named CName
, this is the classs constructor function, which is
automatically called whenever a new instance of the class is created.
The constructor function may be overloaded, to allow different constructor functions to be called according to the parameters.
The constructor function must be declared without any return type.
module.h |
module.cpp |
usercode.cpp |
||
Declaration class CName { public:
CName(void); };CName(params); |
Implementation CName::CName(void) { } CName::CName(params) { } |
Instance CName
nameObject; or CName* pNameObject = new CName; calls constructor. To call the alternative constructor: CName obj(params); CName* pObj = new CName(params); |
If an array of objects is created, the constructor function is called for each object in turn:
Note that calling the constructor always creates a new instance of the class: the constructor cant be called like an ordinary function. Therefore, if a class contains another class as a member variable, that classs constructor cant be called directly. A special syntax is provided for initialising member variables, including member classes:
module.h |
module.cpp |
|||||
Declaration class CName { public: CName(params); };CClass m_class; int m_i1; int m_i2; |
Implementation CName::CName(params) :
m_i2 = n; equivalent to
:m_i2(n) } |
If a class CName
declares a function named ~CName
, this is the classs destructor function, which is
automatically called whenever the object (class instance) goes out of scope -
e.g. at the end of a function where it is locally defined.
module.h |
module.cpp |
|
Declaration class CName { public: ~CName(void); }; |
Implementation CName::~CName(void) { } |
The destructor function has no parameters, and cannot be overloaded.
A class can be derived from a base class. A derived class inherits all data and functions in the base class, except for the constructor and destructor functions.
module.h |
module.cpp |
|
Declaration class CName : public
CBase { public: CName(parameters); }; |
Implementation CName::CName(parameters) :
CBase() { } |
The derived classs constructor should call the base classs
constructor, in the same way as for a member variable (via the ":CBase
" statement).
The derived class may add extra data or functions of its own to those
inherited from the base class. If the derived class defines a variable/function
with the same name as one in the base class, the base class member can still be
accessed (assuming its either public or protected) using "CBase::MemberName
".
A class can be derived from multiple base classes, in which case it inherits all their members.
module.h |
module.cpp |
|
Declaration class CName:
public CBase1, {public CBase2, public CBase3 public: CName(parameters); }; |
Implementation CName::CName(parameters):
CBase1(), {
}CBase2(), CBase3() |
Any name conflicts between the members in the various classes must be
resolved by referring to them using "CBaseN::MemberName
".
The accessiblity of a variable or function depends on whether it follows
a public
, protected
, or private
keyword in the class declaration:
public |
Accessible by any code internal or external ("user" code) to the class. | |
protected |
Only accessible by code internal to the class, or internal to any class derived from this class. Not accessible by any code external to the class. | |
private |
Only accessible by code internal to the class (member functions). Not accessible by a derived class, nor by any code external to the class. |
If the class being declared is derived, the keyword preceding the base class name affects the status of the members that the derived class inherits:
public |
The base class public, protected, private members remain public, protected, private respectively. | |
protected |
The base class public members become protected in the derived class. Member functions in the derived class (and classes derived from it) may access the members, but external code using an instance of the derived class may not. | |
private |
All the base class members become private in the derived class. Member functions in the derived class may access the members, but classes derived from it and external code using an instance of the derived class may not. |
Individual members can inherit a different status if the relevant base class members are listed following the appropriate keyword in the derived class declaration.
module.h |
Base Declaration class CBase
{ public: type
Func(parameters); };Derived Declaration class CDerived : private
CBase { public: CBase::Func; };Func remains public. |
A class can allow a specific other class or function full access to its private and protected members by declaring the class or function as a friend.
module.h |
Declaration class CName1 { friend class CName; public:
friend type Func(parameters); |
A pointer to a base class can be assigned to point to any class derived from that class. However, the pointer can only access members in the base class, even if the derived class has added members of the same name.
module.h |
module.cpp |
usercode.cpp |
||
Base Declaration class CBase
{ public: type
Func(parameters); };Derived Declaration class CDerived: public
CBase { public: type
Func(parameters); }; |
Base Implementation type
CBase::Func(parameters)
{ } Derived Implementation type
CDerived::Func(parameters) { } |
CDerived derivedObj; Creates an instance of the CDerived class (object). CBase* pBaseObj = &derivedObj; Creates a pointer to a CBase object, but the location of the CDerived object is assigned to it. Allowed because CDerived is derived from CBase. pBaseObj->Func(); Calls CBases Func, not CDeriveds Func. |
A function (of the same name) in a base and derived class may be
declared as virtual
. Calls to that function via a pointer to the base class are then linked
at run-time, via a look-up table, so that the function actually called is the
function in the class being pointed to.
module.h |
module.cpp |
usercode.cpp |
||
Base Declaration class CBase
{ public: virtual type
Func(parameters); };Derived Declaration class CDerived: public
CBase { public: virtual type
Func(parameters); }; |
Base Implementation type
CBase::Func(parameters)
{ } Derived Implementation type
CDerived::Func(parameters) { } |
CDerived derivedObj; CBase* pBaseObj = &derivedObj; pBaseObj->Func(); Calls CDeriveds Func. |
The function must be declared identically in the base class and all derived classes that provide their own version.
If the base class doesnt provide an implementation for a virtual function, the function becomes a pure virtual function, and the class becomes an abstract class. It is not allowed nor possible to create an instance of an abstract class: it may only be used to derive classes. A derived class can be created if it provides an implementation for all pure virtual functions it inherits.
module.h |
module.cpp |
usercode.cpp |
||
Base Declaration class CBase
{ public: virtual type Func(params)
= 0; };Derived Declaration class CDerived: public
CBase { public: virtual type
Func(parameters); }; |
Derived Implementation type
CDerived::Func(parameters) { } |
CDerived derivedObj; CBase* pBaseObj = &derivedObj; pBaseObj->Func(); Calls CDeriveds Func. |
The declaration of the pure virtual function must be followed by "= 0
".
Member functions in the base class can call the pure virtual function: the calls will be redirected to the implemented function in the relevant derived class.
static
functions and variablesVariables declared in a class with the static
keyword are common to all objects of that class. This applies even to
variables declared as static
within a member function such a variable is effectively a static
member variable, which can only be accessed from within that
function.
module.h |
module.cpp |
|
Declaration class CName { static type m_Var; }; |
Implementation type CName::m_Var = initial
value; |
Functions declared in a class with the static
keyword can only access static variables (and other static
functions).
const
functionsA member function declared as const
, as in:
can not modify any member variables within that class i.e. the class object is not affected by calling the function.
Functions can be defined which allow standard operators to
be used with user-defined data types (such as classes). Both binary and unary
operators can be overloaded; some (such as "+
") can have both binary and unary overload functions declared.
module.h |
module.cpp |
usercode.cpp |
||
Declaration type operatorop1(type
A); type operatorop2(type A, type B); |
Implementation type operatorop1(type
A) { } type operatorop2(type A, type B) { } |
X = op1 Y; is exactly equivalent to: X = operatorop1(Y); X = Y op2 Z; is exactly equivalent to: X = operatorop2(Y, Z); |
The operator overload function can be declared within the class to which
it applies. Remember that the this
keyword is effectively the first parameter to any function within a
class.
module.h |
module.cpp |
usercode.cpp |
||
Declaration class CName { public: type operatorop1(void); };type operatorop2(CName B); |
Implementation type
CName::operatorop1(void) { } type CName::operatorop2(CName B) { } |
X = op1 Y; is exactly equivalent to: X = Y.operatorop1(); X = Y op2 Z; is exactly equivalent to: X = Y.operatorop2(Z); |
The following operators may be overloaded:
* / + - % ^ & |
~
*= /= += -= %= ^= &= |=
&& || ! , = < > <= >= == !=
++ -- << >> <<= >>= -> ->* [] () new
delete
In addition, user-defined type conversions can be defined:
module.h |
module.cpp |
usercode.cpp |
||
Declaration class CName { public: operator
type(void); }; |
Implementation CName::operator type(void) { } |
CName Y; type X = Y; is exactly equivalent to: type X = Y.operator type(); |
Dynamic casting converts a pointer (or a reference) to one class into a pointer to another (derived or base) class, checking for the validity of the cast. If a run time check fails, the resulting pointer is null, and a bad_cast exception is thrown.
module.h | usercode.cpp | |
class CBase { }; class CDerived : public CBase { }; |
Upcast (derived to base) - only compile time
check needed: CBase* pBase = dynamic_cast<CBase*>(pDerived); Downcast (base to derived) - run time check that the object really is an instance of CDerived: CDerived* pDerived = dynamic_cast<CDerived*>(pBase); Run time check to get a pointer to the complete object: void* pv = dynamic_cast<void*>(pBase); |
Static casting converts any one type to any other type, without any run time checking. It uses any standard or user-defined type conversions (see operator overloading) which are defined.
Const casting keeps the original type, but can remove any const
or volatile
attributes - only really useful with pointers.
Re-interpret casting simply forces a value of one type to be treated as a value of a different type.
By default, all global identifiers (e.g. function, variable, class names) belong to the "global" namespace. However, they can be declared as belonging to a named namespace.
Identifiers only need to be unique within each namespace, allowing a name in one namespace to be duplicated in another. To refer to an identifier in a specific namespace: