Classes
Programming for Telecommunications
Filippo Campagnaro
Programming for TLC
campagn1@[Link]
Outline
1. Classes
2. Member functions
3. Access control
4. Constructors
5. Mutability
Programming for TLC
6. Self-reference
7. Static members
8. Concrete classes
[c++pl] Chapter 16
Classes
• A class introduces an user-defined type, i.e., a
concrete representation of a concept
• The creation of a class allows a programmer to
separate
the details of the the properties essential
implementation to the use of the type
• which kind of variables • the ”interface” that an
are used to represent the external user can use to
object manipulate objects of this
Classes basics
• how the representation type
interacts with these
variables
3
Classes basics
• A class is a user-defined type with a set of members
• Members can be
• data, i.e., variables that represent the state of the type
• functions, i.e., methods that perform initialization, copy, move,
cleanup and all the other actions related to the type
• Members can be
Classes basics
• public, to represent the class interface
• private, to hold the implementation details
4
Classes basics
• It is possible to access to members with the . operator
(for objects) or the -> operator (for pointers to objects)
• It is possible to define operators (e.g., + - []) for the
type
• A class defines invariants, i.e., a property of a type that
Classes basics
holds from its initialization to the destruction
5
Example of class
class X {
// the representation (implementation) is private
private:
int m;
public: // the user interface is public
X(int i =0) :m{i} { } // constructor
// member function with definition
int mf(int i) {
int old = m;
m = i;
Classes basics
return old;
}
};
6
Example of class usage
X var {7};
// a variable of type X, initialized to 7
// a function that interacts with var
int f(X var, X∗ ptr)
{
int x = [Link](7); // access using .
int y = ptr−>mf(9); // access using ->
int z = var.m; // error: cannot access
Classes basics
// private member
}
7
Member functions
• Functions declared within a class definition
• They are invoked only for variables of the appropriate
type
• Definition:
• in a separate location (usually a .cpp file) than the
declaration (usually in header .h file). In this case, the
definition needs to have the name of the class
• in the class declaration
Member functions
• small and rarely modified functions – otherwise, the code that
uses them is recompiled every time the function is modified
• they are implicitly inlined
recall from the class on functions: inline = new code for every function call, instead than of
a single code in memory that is pointed to by every function call.
8
Example of member functions
class X {
...
// member function with inlined definition
int mf(int i) {
int old = m;
m = i;
return old;
}
Member functions
// member function with only declaration
int amf(int j);
};
9
Example of member functions
class X {
...
int amf(int j);
};
// we need to define it elsewhere
int
X::amf(int j)
Member functions
{
return j + 2;
}
10
Access control
It is possible to specify to which members of the class it is
possible to access to from other classes. This is useful
• to control the behavior and what can be changed in the
representation of an object
• to expose only the public way to interact with a class –
easier to update the underlying representation
• no need to recompile code that uses that class
• the programmer can only study the public interface
This is achieved with the public and private labels
Access control
The friend label can be use to indicate exceptions
11
Example of public/private
class X {
// private unless after a public label
int m;
// it is possible to use a private label
private:
int m2;
int doSomething(double d);
// for public members, it is necessary to use a
// public label
public: // the user interface is public
Access control
X(int i =0) :m{i} { } // constructor
};
12
Example of friend classes
class Y {
friend X;
// class x can access both private and public
// members and functions of y
private:
int v;
int doSomething(double d);
// for public members, it is necessary to use a
// public label
public: // the user interface is public
Access control
Y(int i =0) :v{i} { } // constructor
};
13
Structs and classes
• A struct is nothing but a class with all members public by
default
• In general,
• use a struct for a simple data structure
• use a class to enforce invariants
• A class is better at enforcing invariants
• the underlying representation can be hidden to external users,
which can interact with private members only through specific
public methods
• the class developer can make sure that invariants are enforced
Access control
through these public methods
14
Constructors
• Member functions that have the explicit purpose of
initializing objects
• They have the same name of the class, and no return type
• It is possible to use the () and {} notations
(the latter is more consistent with respect to built-it types, and
highlights better what is being done)
Date today = Date(22,2,1992);
Date tmrw = Date{22,2,1992};
• It is possible to have multiple constructors, with different
Constructors
sets of arguments
The same overloading rules for functions apply
15
Explicit constructors
• Implicit conversion: a constructor with a single argument
implicitly converts it to the type of the constructor’s class
• This may not be desirable: the programmer may not want to
construct an object
• It introduces unexpected temporary objects
• explicit keyword prevents a constructor from being used
Constructors
in implicit conversions (otherwise, compilation error)
16
Explicit constructors
class Date { class Date {
public: public:
explicit Date(int d); Date(int d);
} }
// … // …
Date d = 15; // error Date d = 15; // ok, but
Date d {15}; // ok, // not very clear
// {} considered explicit
• It is a good practice to keep single argument constructors
explicit
Constructors
• Unless exceptions, e.g., std::complex<double> c = 1; - it
naturally creates a complex with only the real part
17
In-class initializers
• Classes can have many constructors, accepting different
arguments
• It can be useful to have default values for the data
members
• A constructor can then modify them if needed
class Date {
int d {22};
int m {02}; in-class initialization
int y {1992};
public:
Date(int, int, int); // day, month, year
Date(int, int); // day, month, year is default
Constructors
Date(int); // day, month and year are default
Date(); // default date, 22/02/1992
Date(const char∗); // date in string representation
...
18
}
Mutability
• A name can refer to a object with values which are
• Mutable
• Immutable, i.e., const
• Member functions need to work on const objects
1. Constant member functions const is part of
the type, it must
int getDay() const; be repeated also
in the definition
These functions do not modify the value of the object
• Const member functions work on const and non-const objects
• Non-const member functions do not work on const objects
Mutability
19
Mutability
2. Logical constness
A const member function may need to change a member
data value, without affecting the actual representation
(logical value) of the object
• example: the cache of a string representation of the object value
class Date {
int d {22};
int m {02};
int y {1992};
std::string string_cache;
bool valid_cache;
public:
Mutability
std::string string_rep() const;
}
• string_rep does not change the status of the object, but it may
need to update string_cache if d, m, or y are changed 20
Mutability
To address this:
a. declare members mutable – they can be modified even
in const objects
• this is ok only if a small part of the object needs to change
class Date {
int d {22};
int m {02};
int y {1992};
mutable std::string string_cache;
mutable bool valid_cache;
...
public:
std::string string_rep() const;
private:
void compute_cache_value() const;
Mutability
21
Mutability
class Date {
int d {22};
int m {02};
int y {1992};
mutable std::string string_cache;
mutable bool valid_cache;
...
public:
std::string string_rep() const;
private:
void compute_cache_value() const;
string Date::string_rep() const
{
if (!valid_cache) {
// update string_cache
Mutability
compute_cache_value();
valid_cache = true;
}
return string_cache; 22
}
Mutability
To address this:
b. mutability through indirection – the properties that
need to be updated can be placed in another object,
with a pointer to it as member of the class
• const does not apply to objects accessed through pointers or
references
struct cache { bool valid; string rep; };
class Date {
int d {22}; string Date::string_rep() const
int m {02}; {
int y {1992}; if (!c->valid) {
cache* date_cache; // update
Mutability
... compute_cache_value();
c->valid = true;
}
return c->rep; 23
}
Self-reference
• this is a pointer to the object on which the function was
called
• object of type non-const X -> this has type X*, but is considered
an rvalue (it is not possible to get its address or assign to it)
• object of type const X -> this has type const X*
• most uses are implicit (it is not necessary to specify
this->member_value in member functions)
• it could be useful to return a reference to it to chain
operations
Date& add_year(int year) { y += year; return *this; }
Date& add_month(int month) { m += month; m = m % 12; return *this; }
.....
Classes
Date d {10, 05, 2003} this could be this->m but it is
d.add_year(3).add_month(3); not necessary 24
Static members
• A static member is a variable that is part of a class, but
not of a specific object of the class
• Before the first use, they must be defined!
• There is exactly one copy of a static variable per program
• Static member functions can be called without using an
object
• They may introduce concurrency issues with multi-
threaded programs
class Date {
int d, m, y;
static Date default_date;
public:
Date(int dd =0, int mm =0, int yy =0);
Classes
// ...
static void set_default(int dd, int mm, int yy); 25
// set default_date to Date(dd,mm,yy)
Static members
class Date {
int d, m, y;
static Date default_date;
public:
Date(int dd =0, int mm =0, int yy =0);
// ...
static void set_default(int dd, int mm, int yy);
// set default_date to Date(dd,mm,yy)
};
// implementation (also in some other parts of the
program)
// definition of Date::default_date
Date Date::default_date {16,12,1770};
// definition of Date::set_default
Classes
void Date::set_default(int d, int m, int y) {
// assign new value to default_date
26
default_date = {d,m,y};
Concrete classes
• A “concrete” class defines a small, concrete type
Concrete class Abstract class
its representation is part vs interface to multiple
of the definition possible implementations
(e.g., some methods are declared but not defined)
• This allows us to
• place concrete objects in the stack, to allocate them statically in
memory or in other objects
• copy & move objects
Concrete classes
• used objects as named variables (instead than using pointers and
references)
• These classes represent simple user-defined types that
yield optimal compiler-generated code
• Value-oriented paradigm (not OOP) 27
Concrete classes
They typically have
• Constructor
• Functions to examine an object (marked as const)
• Functions to modify the object (without the need to know
its representation)
not necessarily in the
• (in case) Classes to report errors class definition, but – for
• (in case) Helper functions example – they can be in
the same namespace
Concrete classes
• Functions to copy and move the objects
See the example Course class in the code for this lesson!
28