Classes Continued¶
Rule of Five/Three/Zero¶
Rule of Three
- If a class requires user-defined destructor, a user-defined copy constructor, or a user-defined copy assignment operator, it almost certainly requires all three.
- Corollary: if you delete one them, you most likely want to delete all three
Rule of Five
- If you want move semantics, you have to provide all five special functions.
- If you forget move constructor and move assignment operator - missed optimization opportunity
Rule of Zero
- If you build things out of standard library components to manage your resources, you don’t have to provide any of the special functions.
- The same bare-bones graph, but with
std::vector
: rule0.cpp
- The same bare-bones graph, but with
More About Special Methods¶
- Deleting with
= delete
- It is possible to delete a constructor (or any other function) that has been generated automatically
- For instance deleting a copy constructor, such that an object cannot be copied
- Defaulting with
= default
- It is possible to emphasize that we actually want to have an automatically generated function, for instance, to document that the automatically generated move constructor/assignment operator exists
- Rule of five still applies...
RAII Principle¶
-
Resources Acquisition is Initialization Principle
- There is no automatic memory management in C++
- Therefore it is attractive to attach resource management to construction and destruction of stack-allocated objects
- The resource is encapsulated in a class together with allocation and release member functions
Smart Pointers¶
std::unique_ptr
– for unique ownershipstd::shared_ptr
– for shared ownershipstd::weak_ptr
– for temporary ownership (with possibility for safely dangling)
The first two:
- provides overloads for
operator*
andoperator->
- can be null
- custom deleters are possible (but handle differently...)
- smart_pointers.cpp
Type Conversion¶
Explicit Type Conversion¶
Explicit conversions to type T
(casts):
static_cast<T>(expr)
from a related type- Can activate built-in or user-defined type conversion, conversion operators, and implicit/explicit constructors.
reinterpret_cast<T>(expr)
from an unrelated type - "dangerous"- Can cast between pointer types, and between integer and pointer types
- Provides a value of new type that has the same bit pattern as its argument.
dynamic_cast<T*>(expr)
from a related polymorphic type (pointer or reference types only)const_cast<T>(expr)
from a closely related type (add or remove const qualifier)- C-style type casts:
(T)expr
orT(expr)
using early C++ notation
"If you are doing a lot of explicit conversions, you are doing something wrong..."
Const Member Functions¶
-
A constant member function is not allowed to change the state of the object.
- On a constant object, only constant member functions can be called.
- A const member function cannot call other member functions which are not constant!
- Point class
-
Difference between logical constness and physical constness
- For example, for efficiency, I may cash results of some expensive computations.
- mutable data members can always be updated, even if they belong to a const object
Inline Member Functions¶
- Given by the
inline
keyword and member functions defined inside class definitions are implicitly marked as inlined - An efficiency concern - eliminates a call
- A plea to the compiler - not a requirement
- Inline functions must be defined in every translation unit where they are used, thus they are usually defined in header files
- Some functions cannot easily be inlined
- recursive functions
- Two ways to specify them
- Write a body in the class definition (only if it is very brief)
- Provide the definition of the member function in the same header file
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Friendship¶
- Friendship is provided by the class that encapsulates members with access limitations
- Friendship cannot be taken by a class or function that wants access!
- Friendship can be granted to:
- an ordinary function, or to an overloaded operator
-
f(x,y)
versusx.f(y)
call syntax
-
- a member function in another class
- all members of another class
- an ordinary function, or to an overloaded operator
- Friendship is not transitive, and it is not inherited
Example: operators <<
and >>
: header, cpp
Operator Overloading¶
Restrictions:
- It is not possible to invent new operator symbols.
- The associativity and precedence of the predefined rules of predefined operators apply.
- Cannot be overloaded:
::
,.
,.*
,?:
,sizeof
,typeid
- At least one operand must be of a user-defined type.
- If the left operand is of user-defined type, the operator may be defined as a member function
- If the left operand is of predefined type, the operator must be a non-member function
Example: point3.h, point3.cpp
Example of operator(), operator int()
: functor.cpp
- Implementing lambda through function objects
STL: string¶
string
is an alias for abasic_string
parameterized bychar
- As everything in STL, strings have value semantics
- Copied in and out of functions - or passed by reference
- Characters in strings can be accessed in checked mode and unchecked mode
- Checked mode:
s.at(i)
- Unchecked mode:
s[i]
- Checked mode:
- A string is mutable
- Strings can be copy constructed based on a C-style string
string s{"Peter"};
string s("Peter");
string s = "Peter";
- Short string optimization
- Short strings are allocated in the string object itself (not on the free store)
STL: vector¶
- A template class - type parameterized
- Not of fixed size like an array – the number of elements may be adjusted dynamically
- Size and capacity:
- Size: the actual number of elements in the vector
- Capacity: the maximum number of elements before resizing is needed.
- With or without range checking.
- Obeys value semantics and stores values
- It wraps a pointer to a heap storage
- Traversed with use of iterators. Iterators can be used in a similar way as pointers, via overloading of operators
*iterator
,iterator++
,iterator + n
,iterator1 - iterator2
std::ostream and std::istream¶
Considerations about IO in C++:
- IO functions must apply uniformly to pre-defined types and user-defined types
- The C-style
printf
andscanf
are not easy to generalize to user-defined functions - In addition,
printf
andscanf
are not type safe
- The C-style
- Use of overloaded operators seems attractive
- Shorter, and easier to spot:
s << d1 << d2 << d3
- The relative low priority of
<<
is practical when values of expressions must be printed.cout << x + y * z
and notcout << (x + y * z)
- Shorter, and easier to spot:
Standard Streams and Files¶
cin
: Standard character input – typically defaulted to a keyboardcout
: Standard character output – typically defaulted to a screencerr
: Standard character error output – unbufferedclog
: Standard character error output – buffered
Manipulators:
1 2 3 |
|
Last update:
June 15, 2021