0% found this document useful (0 votes)
3 views

Module 54

Uploaded by

deva.jntuk.cse
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views

Module 54

Uploaded by

deva.jntuk.cse
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 34

Module M54

L
Partha Pratim
Das
Programming in Modern C++

E
Objectives &
Outlines
Module M54: C++11 and beyond: Class Features

T
=default /
=delete

P
Control of default
move and copy
Compiler Rules
Partha Pratim Das

N
User Guidelines

Delegating
Constructors Department of Computer Science and Engineering
In-class Init. Indian Institute of Technology, Kharagpur
Inheriting
Constructors [email protected]
Override Controls
override
final
All url’s in this module have been accessed in September, 2021 and found to be functional
explicit
Conversion
bool

Module Summary
Programming in Modern C++ Partha Pratim Das M54.1
Module Recap

Module M54

• Learnt different techniques without or with std::function to write and use

L
Partha Pratim
Das
non-recursive and recursive λ expressions in C++11 / C++14

E
Objectives &
Outlines • Several practice examples to be tried and tested

T
=default /
=delete

P
Control of default
move and copy
Compiler Rules

N
User Guidelines

Delegating
Constructors

In-class Init.

Inheriting
Constructors

Override Controls
override
final
explicit
Conversion
bool

Module Summary
Programming in Modern C++ Partha Pratim Das M54.2
Module Objectives

Module M54

• Introducing class features in C++11:

L
Partha Pratim
Das
◦ =default and =delete

E
Objectives &
Outlines ◦ Control of default move and copy
◦ Delegating constructors

T
=default /
=delete
◦ In-class member initializers

P
Control of default
move and copy ◦ Inherited constructors
Compiler Rules
◦ Override controls: override & final

N
User Guidelines

Delegating ◦ Explicit conversion operators


Constructors

In-class Init.
• These features enhance OOP, generic programming, readability, type-safety, and
Inheriting performance in C++11
Constructors

Override Controls
override
final
explicit
Conversion
bool

Module Summary
Programming in Modern C++ Partha Pratim Das M54.3
Module Outline

Module M54
1 =default / =delete Functions

L
Partha Pratim
Das
2 Control of default move and copy

E
Objectives &
Outlines
Compiler Rules
User Guidelines

T
=default /
=delete
3 Delegating Constructors

P
Control of default
move and copy
Compiler Rules 4 In-class Member Initializers

N
User Guidelines

Delegating 5 Inheriting Constructors


Constructors

In-class Init. 6 Override Controls


Inheriting override
Constructors
final
Override Controls
override
final
7 explicit Conversion Operators
explicit bool
Conversion
bool 8 Module Summary
Module Summary
Programming in Modern C++ Partha Pratim Das M54.4
default / delete Functions

Module M54
Sources:

L
Partha Pratim
Das
=default and =delete, isocpp.org
• C++ Class and Preventing Object Copy, ariya.io, 2015
• C++ Core Guidelines, github.com

E
Objectives &
Outlines ◦ C.20: If you can avoid defining default operations, do
◦ C.21: If you define or =delete any copy, move, or destructor function, define or =delete them all

T
=default /
=delete ◦ C.22: Make default operations consistent

P
Control of default An Overview of the New C++ (C++11/14), Scott Meyers Training Courses
move and copy
Compiler Rules

N
User Guidelines

Delegating
Constructors

In-class Init.

Inheriting
Constructors

Override Controls default / delete Functions


override
final
explicit
Conversion
bool

Module Summary
Programming in Modern C++ Partha Pratim Das M54.5
=default and =delete

Module M54 • The idiom of prohibiting copying (for C++03 recall Module 25) can now be expressed directly:
class X { // ...

L
Partha Pratim
Das X& operator=(const X&) = delete; // Disallow copying
X(const X&) = delete;

E
Objectives &
Outlines };

T
=default /
=delete
• Conversely, we can also say explicitly that we want default copy behavior:
class Y { // ...

P
Control of default
move and copy Y& operator=(const Y&) = default; // default copy semantics
Compiler Rules Y(const Y&) = default;

N
User Guidelines
};
Delegating
Constructors • Explicitly writing out the default by hand is good for readability, but it has two drawbacks:
In-class Init. ◦ it sometimes generates less efficient code than the compiler-generated default would, and
Inheriting ◦ it prevents types from being considered PODs
Constructors

Override Controls
• The =default mechanism can be used for any function that has a default
override • The =delete mechanism can be used for any function like to eliminate an undesired conversion:
final
struct Z { // ...
explicit
Conversion
Z(long long); // can initialize with a long long
bool Z(long) = delete; // but not anything smaller
Module Summary };
Programming in Modern C++ Partha Pratim Das M54.6
default Member Functions

Module M54
• The special member functions are implicitly generated if used:

L
Partha Pratim
Das ◦ Default constructor
. Only if no user-declared constructors

E
Objectives &
Outlines
◦ Destructor

T
=default /
=delete ◦ Copy operations (copy constructor, copy operator=)

P
Control of default
move and copy . Only if move operations not user-declared
Compiler Rules
◦ Move operations (move constructor, move operator=)

N
User Guidelines

Delegating . Only if copy operations and destructor not user-declared


Constructors

In-class Init.
• Generated versions are:
Inheriting ◦ Public
Constructors

Override Controls
◦ Inline
override ◦ Non-explicit
final
explicit
• defaulted member functions have:
Conversion
bool ◦ User-specified declarations with the usual compiler-generated implementations
Module Summary
Programming in Modern C++ Partha Pratim Das M54.7
default Member Functions

Module M54

• Typical use: unsuppress implicitly-generated functions:

L
Partha Pratim
Das
class Widget { public:

E
Objectives & Widget(const Widget&); // copy ctor prevents implicitly declared
Outlines
// default ctor & move ops

T
=default /
=delete
Widget() = default; // declare default ctor, use default impl.
Widget(Widget&&) noexcept = default; // declare move ctor, use default impl.

P
Control of default
move and copy ...
Compiler Rules };

N
User Guidelines

Delegating
Constructors • Or change normal accessibility, explicitness, virtualness:
In-class Init.
class Widget { public:
Inheriting
Constructors
virtual ~Widget() = default; // declare as virtual
explicit Widget(const Widget&) = default; // declare as explicit
Override Controls
override private:
final Widget& operator=(Widget&&) noexcept = default; // declare as private
explicit ...
Conversion
};
bool

Module Summary
Programming in Modern C++ Partha Pratim Das M54.8
delete Functions

Module M54

• deleted functions are defined, but cannot be used

L
Partha Pratim
Das
◦ Most common application: prevent object copying:

E
Objectives &
Outlines class Widget {
Widget(const Widget&) = delete; // declare and

T
=default /
=delete Widget& operator=(const Widget&) = delete; // make uncallable
...

P
Control of default
move and copy };
Compiler Rules

N
User Guidelines

Delegating • Note that Widget is not movable, either


Constructors

In-class Init. ◦ Declaring copy operations suppresses implicit move operations!


Inheriting ◦ It works both ways:
Constructors
class Gadget {
Override Controls
Gadget(Gadget&&) = delete; // these also
override
final Gadget& operator=(Gadget&&) = delete; // suppress copy operations
explicit ...
Conversion };
bool

Module Summary
Programming in Modern C++ Partha Pratim Das M54.9
delete Functions

Module M54

• Not limited to member functions

L
Partha Pratim
Das
◦ Another common application: control argument conversions

E
Objectives &
Outlines . deleted functions are declared, hence participate in overload resolution:

T
=default /
=delete
void f(void*); // f callable with any ptr type

P
Control of default
move and copy
void f(const char*) = delete; // f uncallable with [const] char*
Compiler Rules auto p1 = new std::list<int>; // p1 is of type std::list<int>*

N
User Guidelines extern char *p2;
Delegating ...
Constructors
f(p1); // fine, calls f(void*)
In-class Init. f(p2); // error: f(const char*) unavailable
Inheriting f("Modern C++"); // error
Constructors
f(u"Modern C++"); // fine (char16 t* != char*)
Override Controls
override
final
explicit
Conversion
bool

Module Summary
Programming in Modern C++ Partha Pratim Das M54.10
Control of default move and copy

Module M54
Sources:

L
Partha Pratim
Das
Control of default move and copy, isocpp.org
• The rule of three/five/zero, cppreference.com
• C++ Core Guidelines, Eds. Bjarne Stroustrup and Herb Sutter, 2022

E
Objectives &
Outlines ◦ C.20: If you can avoid defining default operations, do
◦ C.21: If you define or =delete any copy, move, or destructor function, define or =delete them all

T
=default /
=delete ◦ C.22: Make default operations consistent

P
Control of default An Overview of the New C++ (C++11/14), Scott Meyers Training Courses
move and copy
Compiler Rules

N
User Guidelines

Delegating
Constructors

In-class Init.

Inheriting
Constructors Control of default move and copy
Override Controls
override
final
explicit
Conversion
bool

Module Summary
Programming in Modern C++ Partha Pratim Das M54.11
Control of default move and copy

Module M54
• We learnt in Module 51 that Move is an Optimization of Copy. This is specifically true for
classes having resources (like pointer / vector) that needs to be moved or copied

L
Partha Pratim
Das
• This needs Move and Copy operations to be appropriately defined

E
Objectives &
Outlines
• We also need a destructor in such cases for the release of the resources (like pointer)
• Further, the compiler provide these functions as default (if not provided and / or deleted by the

T
=default /
=delete user) so that the users do not need to write them for every class

P
Control of default
move and copy
So there can be one of the following options for each of the five functions in a class:
Compiler Rules [1] [Un-declared] Do not mention the function in the class - implicitly default

N
User Guidelines
[2] [=default] Mention the function as =default - explicitly default
Delegating
Constructors [3] [Declared] Declare the function but not define it - prohibit use
In-class Init. [4] [=deleted] Mention the function as =deleted - prohibit use
Inheriting [5] [Defined] Provide a user-defined implementation of the function - proper use
Constructors

Override Controls
• For [1] & [2] compiler provides default implementation and for [5] user provides the same
override • In total, we have 5 × 5 = 25 scenarios but only a few of them are semantically consistent
final
• So for a proper semantics, we need to control move / copy / destruction:
explicit
Conversion ◦ Compiler follows a set of rules
bool
◦ User needs to follow a set of guidelines
Module Summary
Programming in Modern C++ Partha Pratim Das M54.12
Control of default move and copy: Compiler Rules

Module M54 • Move Rules


◦ If any move, copy, or destructor is explicitly specified (declared, defined, =default,

L
Partha Pratim
Das
or =delete) by the user:

E
Objectives &
Outlines . no move is generated by default

T
=default /
=delete
. any declared but un-defined move is a linker error
. any =default move is compiler default

P
Control of default
move and copy
Compiler Rules
. any =delete move is compilation error
. any un-declared move defaults to corresponding copy

N
User Guidelines

Delegating
Constructors • Comment / =default / =delete different functions below to understand the rules of
In-class Init. move as well as copy. Note that a default function will not stream any string
Inheriting class X { public: int main() {
Constructors X() { std::cout << "Ctor "; } X x1;
Override Controls X(const X&) { std::cout << "C-Ctor "; } X x2 { x1 };
override X& operator=(const X&) { std::cout << "C= "; return *this; } x1 = x2;
final X(X&&) { std::cout << "Mtor "; } X x3 { std::move(x1) };
explicit X& operator=(X&&) { std::cout << "M= "; return *this; } x2 = std::move(x3);
Conversion ~X() { } }
bool }; // Ctor C-Ctor C= Mtor M=
Module Summary
Programming in Modern C++ Partha Pratim Das M54.13
Control of default move and copy: Compiler Rules

Module M54
• Copy Rules

L
Partha Pratim
Das ◦ If any copy or destructor is explicitly specified (declared, defined, =default, or
=delete) by the user:

E
Objectives &
Outlines
. any undeclared copy operations are generated by default

T
=default /
=delete . this is deprecated in C++11
◦ If any move is explicitly specified (declared, defined, =default, or =delete):

P
Control of default
move and copy
Compiler Rules
. no copy is generated by default

N
User Guidelines

Delegating ◦ Bad problem due to default copy in C++03 persists in C++11 onward
Constructors
class X { public: // copyable class
In-class Init. ~X() { delete p; } // implicit invariant: p owns *p
Inheriting //... // no copy ops declared
Constructors
private: int *p;
Override Controls
};
override
final int main() {
explicit X x1;
Conversion X x2(x1);
bool
} // double delete! of p: run-time error: munmap_chunk(): invalid pointer in gcc
Module Summary
Programming in Modern C++ Partha Pratim Das M54.14
Control of default move and copy: User Guidelines

Module M54
• C++ Core Guidelines, 2022 (Bjarne Stroustrup & Herb Sutter) provides 3 guidelines:

L
Partha Pratim
Das ◦ [Rule of zero]: C.20: If you can avoid defining default operations, do
. Classes with custom Dtors, copy/move Ctors or assignment needs exclusive ownership

E
Objectives &
Outlines
. Other classes should not have these custom functions

T
=default /
=delete ◦ [Rule of five]: C.21: If you define or =delete any copy, move, or destructor function,
define or =delete them all

P
Control of default
move and copy
Compiler Rules . As the presence of a user-defined (or = default or = delete declared) Dtor, copy Ctor or

N
User Guidelines assignment prevents implicit definition of the move Ctor and assignment, any class for
Delegating
Constructors
which move semantics are desirable, has to declare all five special member functions
In-class Init.
. [Rule of three]: If a class requires a user-defined Dtor, a user-defined copy Ctor, or a
Inheriting
user-defined copy assignment, it almost certainly requires all three
Constructors
◦ C.22: Make default operations consistent
Override Controls
override . Default operations have a matched set and interrelated semantics. It is a surprise
final
− if copy/move construction and assignment do logically different things
explicit
Conversion − if constructors and destructors do not provide a consistent view of resource mgmt.
bool
− if copy and move do not reflect the way constructors and destructors work
Module Summary
Programming in Modern C++ Partha Pratim Das M54.15
Delegating Constructors

Module M54

L
Partha Pratim
Das

E
Objectives &
Outlines

T
=default /
=delete

P
Control of default
move and copy
Compiler Rules

N
User Guidelines

Delegating
Constructors

In-class Init.

Inheriting
Constructors

Override Controls
Delegating Constructors
override
final Sources:
explicit • Delegating constructors, isocpp.org
Conversion • An Overview of the New C++ (C++11/14), Scott Meyers Training Courses
bool

Module Summary
Programming in Modern C++ Partha Pratim Das M54.16
Delegating Constructors
Multiple constructors with code copies
Module M54 class Base { public:
Widget::Widget(): // #1
explicit Base(int);

L
Partha Pratim Base(calc()), size(0), flex(defaultFlex) {
Das // ...
regObj(this);
};
}

E
Objectives & class Widget: public Base { public: // 4 Ctors
Outlines Widget::Widget(double fl): // #2
Widget();
Base(calc()), size(0), flex(fl) {

T
=default / explicit Widget(double fl);
=delete regObj(this);
explicit Widget(int sz);
}
Widget(const Widget& w);

P
Control of default
move and copy
Widget::Widget(int sz): // #3
private:
Compiler Rules
Base(calc()), size(sz), flex(defaultFlex) {
static int calc(); // calculate Base value
regObj(this);

N
User Guidelines
static constexpr double defaultFlex = 1.5;
}
Delegating const int size;
Constructors
Widget::Widget(const Widget& w): Base(w), // #4
long double flex;
size(w.size), flex(w.flex) { regObj(this); }
In-class Init. };
Refactored for better reuse with delegated constructors
Inheriting
Constructors class Widget: public Base { public: // delegation happens when one Ctor calls another - code refactored
Override Controls
Widget(): Widget(defaultFlex) {} // #1: calls #2
override
explicit Widget(double fl): Widget(0, fl) {} // #2: calls #5
final explicit Widget(int sz): Widget(sz, defaultFlex) {} // #3: calls #5
Widget(const Widget& w): Base(w), size(w.size), flex(w.flex) { regObj(this); } // #4: same
explicit
Conversion private: Widget(int sz, double fl): Base(calc()), size(sz), flex(fl) { regObj(this); } // #5: new
bool // ... same as above
};
Module Summary
Programming in Modern C++ Partha Pratim Das M54.17
Delegating Constructors

Module M54
• Delegation is independent of constructor characteristics

L
Partha Pratim
Das ◦ Delegator and delegatee may each be inline, explicit, public / protected /
private, etc.

E
Objectives &
Outlines
◦ Delegatees can themselves delegate

T
=default /
=delete ◦ Delegators’ code bodies execute when delegatees return:

P
Control of default
move and copy
Compiler Rules
class Data { int i;
public:

N
User Guidelines

Delegating
Data(): Data(0) { cout << "Data()" << endl; } // #1: calls delegated #2
Constructors Data(int i): i(i) { cout << "Data(int)" << endl; } // #2
In-class Init. };
Inheriting
Constructors int main() {
Override Controls Data d;
override }
final
explicit
Conversion // Data(int)
bool // Data()
Module Summary
Programming in Modern C++ Partha Pratim Das M54.18
In-class Member Initializers

Module M54

L
Partha Pratim
Das

E
Objectives &
Outlines

T
=default /
=delete

P
Control of default
move and copy
Compiler Rules

N
User Guidelines

Delegating
Constructors

In-class Init.

Inheriting
Constructors

Override Controls
In-class Member Initializers
override
final Sources:
explicit • In-class member initializers, isocpp.org
Conversion • An Overview of the New C++ (C++11/14), Scott Meyers Training Courses
bool

Module Summary
Programming in Modern C++ Partha Pratim Das M54.19
In-class Member Initializers

Module M54
• In C++03, only static const members of integral types can be initialized in-class only
with a constant expression so that the initialization can be done at compile-time:

L
Partha Pratim
Das

E
Objectives &
Outlines
int var = 7;
class X {

T
=default /
=delete static const int m1 = 7; // okay
const int m2 = 7; // error: not static

P
Control of default
move and copy static int m3 = 7; // error: not const
Compiler Rules
static const int m4 = var; // error: initializer not constant expression

N
User Guidelines
static const string m5 = "odd"; // error: not integral type
Delegating
Constructors // ...
In-class Init.
};
Inheriting • In C++11 a non-static data member may be initialized where it is declared in its class.
Constructors

Override Controls
A constructor can then use the initializer when run-time initialization is needed:
override
final class A { public: // C++03 class A { public: // C++11
explicit
int a; int a = 7;
Conversion A() : a(7) { } };
bool
};
Module Summary
Programming in Modern C++ Partha Pratim Das M54.20
In-class Member Initializers

Module M54 • This is useful for classes with multiple constructors. Often, all constructors use a common
initializer for a member:

L
Partha Pratim
Das

class A { public: int a, b; // C++03 class A { public: int a, b; // C++11

E
Objectives &
Outlines A(): a(7), b(5), A(): a(7), b(5)
h_algo("MD5"), s("Ctor run") { } { }

T
=default /
=delete
A(int a_val): a(a_val), b(5), A(int a_val): a(a_val), b(5)
h_algo("MD5"), s("Ctor run") { } { }

P
Control of default A(D d): a(7), b(g(d)), A(D d): a(7), b(g(d))
move and copy
Compiler Rules
h_algo("MD5"), s("Ctor run") { } { }
private: HashingFunction h_algo; // Hash algo private: HashingFunction h_algo{"MD5"}; // Hash algo

N
User Guidelines
std::string s; // Tracer std::string s{"Ctor run"}; // Tracer
Delegating
Constructors
}; };

In-class Init. • If a member is initialized by both an in-class initializer and a constructor, only the constructor’s
Inheriting initialization is done (it “overrides” the default). So we can simplify further:
Constructors
class A { public: int a = 7, b = 5; // default initializers
Override Controls A() { }
override A(int a_val): a(a_val) { } // Ctor initialization overrides
final
A(D d): b(g(d)) { } // Ctor initialization overrides
explicit private: HashingFunction h_algo{"MD5"}; // Hash algo: Crypto. hash to be applied to all A instances
Conversion
std::string s{"Ctor run"}; // Tracer: String indicating state in object lifecycle
bool
};
Module Summary
Programming in Modern C++ Partha Pratim Das M54.21
Inheriting Constructors

Module M54

L
Partha Pratim
Das

E
Objectives &
Outlines

T
=default /
=delete

P
Control of default
move and copy
Compiler Rules

N
User Guidelines

Delegating
Constructors

In-class Init.

Inheriting
Constructors

Override Controls
Inheriting Constructors
override
final Sources:
explicit • Inherited constructors, isocpp.org
Conversion • An Overview of the New C++ (C++11/14), Scott Meyers Training Courses
bool

Module Summary
Programming in Modern C++ Partha Pratim Das M54.22
Inheriting Constructors

Module M54

A member of a base class is not in the same We can “lift” a set of overloaded functions

L
Partha Pratim
Das scope as a member of a derived class: from a base class into a derived class:

E
Objectives &
Outlines struct B { void f(double); }; struct B { void f(double); };
struct D : B { struct D : B {

T
=default /
=delete using B::f; // bring all f()s from B into scope
void f(int); void f(int); // add a new f()

P
Control of default
move and copy }; };
Compiler Rules B b; b.f(4.5); // fine B b; b.f(4.5); // fine

N
User Guidelines // surprise: calls f(int) with argument 4 // fine: calls D::f(double) which is B::f(double)
Delegating
D d; d.f(4.5); D d; d.f(4.5);
Constructors

In-class Init. • Stroustrup has said that “Little more than a historical accident prevents using this to
Inheriting work for a constructor as well as for an ordinary member function”
Constructors

Override Controls • C++11 provides that facility to life a base class constructor into the derived class
override
final • We present an illustrative example for various svenarios
explicit
Conversion
bool

Module Summary
Programming in Modern C++ Partha Pratim Das M54.23
Inheriting Constructors
#include <iostream>
Module M54 #include <string>

L
Partha Pratim
Das class B { public: // Base class
B() { std::cout << "B::B() "; }

E
Objectives & B(int) { std::cout << "B::B(int) "; }
Outlines void f(int) { std::cout << "B::f(int) "; }

T
=default / };
=delete class D : public B { public: // Derived class
using B::f; // lift B::f into D’s scope -- works in C++03 and C++11

P
Control of default
move and copy void f(string) { std::cout << "D::f(string) "; } // provide a new overload f
Compiler Rules void f(int) { std::cout << "D::f(int) "; } // prefer this override f to B::f(int)

N
User Guidelines using B::B; // lift B::B into D’s scope -- new in C++11 -- Inheriting Constructors
Delegating // causes implicit declaration of D::D() (or D::D(int)), which, if used, calls B::B() (or B::B(int))
Constructors D(const string&) { std::cout << "D::D(string) "; } // provide a new overloaded constructor
In-class Init. D(int): B(0) { std::cout << "D::D(int) "; } // prefer this overloaded constructor to B::B(int)
};
Inheriting
Constructors
int main() {
B b(5); std::cout << std::endl; // B::B(int)
Override Controls D d; std::cout << std::endl; // B::B() // okay due to ctor inheritance if D::D() is undclared
override
D d1(2); std::cout << std::endl; // B::B(int) D::D(int)
final
D d2("ppd"); std::cout << std::endl; // B::B() D::D(string)
explicit b.f(3); std::cout << std::endl; // B::f(int)
Conversion
d1.f(1); std::cout << std::endl; // D::f(int)
bool
d2.f("cd"); std::cout << std::endl; // D::f(string)
Module Summary }
Programming in Modern C++ Partha Pratim Das M54.24
Inheriting Constructors
class B: B::B(); B::B(int); B::f(int);
Module M54
class D: using B::f; D::f(string); D::f(int); using B::B; D::D(const string&); D::D(int);

L
Partha Pratim
Das
// using B::B; // using B::B; using B::B; using B::B;
Calls // D(const string&); D(const string&); D(const string&); D(const string&);

E
Objectives &
Outlines // D(int): B(0); // D(int): B(0); // D(int): B(0); D(int): B(0);

T
=default /
=delete
B b(5); okay okay B::B(int) B::B(int)

P
Control of default D d; okay error: D::D() B::B() B::B()
move and copy error: D::D(int) error: D::D(int)
D d1(2); B::B(int) B::B(int) D::D(int)
Compiler Rules
D d2("ppd"); error: D::D(const char[4]) okay B::B() D::D(string) B::B() D::D(string)

N
User Guidelines
B::B(int) hidden B::B(int) hidden D exposes B::B’s Overloads
Delegating
Constructors

In-class Init. // using B::f; // using B::f; using B::f; using B::f;
Inheriting Calls // void f(string); void f(string); void f(string); void f(string);
Constructors // void f(int); // void f(int); // void f(int); void f(int);
Override Controls
override
final b.f(3); okay: B::f(int) okay: B::f(int) B::f(int) B::f(int)
d1.f(1); okay: B::f(int) error: D::f(int) B::f(int) D::f(int)
explicit
Conversion d2.f("cd"); error: D::f(const char*) okay: D::f(string) D::f(string) D::f(string)
bool D inherits B::f(int) B::f(int) hidden D exposes B::f(int) Overload + Override
Module Summary
Programming in Modern C++ Partha Pratim Das M54.25
Inheriting Constructors: Member Initialization in Derived Class

Module M54
• Inheriting constructors into classes with data members risky. Consider a base class B:

L
Partha Pratim
Das class B { public:
explicit B(int);

E
Objectives &
Outlines
};
• Derive a class D with data members:

T
=default /
=delete

P
Control of default
move and copy
Default Initialization In-class Initialization
Compiler Rules class D: public B { class D: public B {

N
User Guidelines
public: public:
Delegating using B::B; // Inherits B::B(int) using B::B; // Inherits B::B(int)
Constructors
private: private:
In-class Init.
std::u16string name; std::u16string name = "Uninitialized";
Inheriting int x = 0, y = 0;
Constructors
int x, y;
}; };
Override Controls
override D d(10); // compiles, but D d(10); // d.name == "Uninitialized",
final // d.name is default-initialized, and // d.x == d.y == 0
explicit // d.x and d.y are uninitialized
Conversion
bool • Use in-class member initialization when inheriting constructor/s
Module Summary
Programming in Modern C++ Partha Pratim Das M54.26
Override Controls: override & final

Module M54
Sources:

L
Partha Pratim
Das
Override controls: override, isocpp.org
• Override controls: final, isocpp.org
• An Overview of the New C++ (C++11/14), Scott Meyers Training Courses

E
Objectives &
Outlines • Simulating final Class in C++, geeksforgeeks.org
• Virtual, final and override in C++, 2020

T
=default /
=delete • Why make your classes final?, Andrzej’s C++ blog, 2012
• In C++, when should I use final in virtual method declaration?, stackexchange.com

P
Control of default
move and copy
Compiler Rules

N
User Guidelines

Delegating
Constructors

In-class Init.

Inheriting
Constructors

Override Controls
override Override Controls: override & final
final
explicit
Conversion
bool

Module Summary
Programming in Modern C++ Partha Pratim Das M54.27
Override Controls: override

Module M54 struct B { // a base class


virtual void f();

L
Partha Pratim
Das
virtual void g() const; // may be overridden only by const member function
virtual void h(char);
void k(); // not virtual

E
Objectives &
Outlines };

T
=default / A function in a derived class overrides a function May be confusing and problematic if a compiler
=delete
in a base class by scoping (without annotation): does not warn against suspicious code:

P
Control of default
move and copy struct D : B { struct D : B {
Compiler Rules void f(); // overrides B::f() void f() override; // okay: overrides B::f()
void g(); // no override w/o const void g() override; // error: wrong type

N
User Guidelines
virtual void h(char); // overrides B::h() virtual void h(char); // overrides B::h(): warning?
Delegating
Constructors void k(); // no override: B::k() is not virtual) void k() override; // error: B::k() is not virtual
}; };
In-class Init.

Inheriting
• Did the user mean to override B::g()? (almost certainly yes)
Constructors • Did the user mean to override B::h(char)? (probably not because of the redundant explicit virtual)
Override Controls • Did the user mean to override B::k()? (probably, but that’s not possible)
override • Note:
final
◦ A declaration marked override is only valid if there is a function to override. The problem with h()
explicit
Conversion may not be caught (because it is correct by the language definition) but it is easily diagnosed
bool ◦ override is only a contextual keyword, so you can still use it as an identifier (not recommended)
Module Summary
Programming in Modern C++ Partha Pratim Das M54.28
Override Controls: final

Module M54 • Sometimes, a programmer wants to prevent a virtual function from being overridden. This can be
achieved by adding the specifier final. For example:

L
Partha Pratim
Das struct B {
virtual void f() const final; // do not override

E
Objectives & virtual void g();
Outlines
};

T
=default / struct D : B {
=delete void f() const; // error: D::f attempts to override final B::f
void g(); // okay

P
Control of default
move and copy };
Compiler Rules
• Why should we use final in C++?

N
User Guidelines

Delegating ◦ If it is performance (inlining) we want or we simply never want to override, it is typically better not
Constructors
to define a function to be virtual
In-class Init. ◦ This is in contrast to Java where all functions are virtual and final provides better performance
Inheriting
Constructors
• It should be used sparingly with care because in a way it contradicts the polymorphic design and in
C++ there are other ways to circumvent the required issues in a hierarchy
Override Controls
override
• Note:
final ◦ The final keyword applies to member function, but unlike override, it also applies to types:
explicit class X final { /* ... */ };
Conversion
bool This prevent the type X to be inherited from
Module Summary
◦ final is only a contextual keyword, so you can still use it as an identifier (not recommended)
Programming in Modern C++ Partha Pratim Das M54.29
explicit Conversion Operators

Module M54

L
Partha Pratim
Das

E
Objectives &
Outlines

T
=default /
=delete

P
Control of default
move and copy
Compiler Rules

N
User Guidelines

Delegating
Constructors

In-class Init.

Inheriting
Constructors

Override Controls
explicit Conversion Operators
override
final Sources:
explicit • Explicit conversion operators, isocpp.org
Conversion • explicit specifier, cppreference
bool
• An Overview of the New C++ (C++11/14), Scott Meyers Training Courses
Module Summary
Programming in Modern C++ Partha Pratim Das M54.30
explicit Conversion Operators
#include <iostream>
Module M54
#include <string>
using namespace std;

L
Partha Pratim
Das struct Y { explicit Y(const string&) { cout << "Y(string)" << ’ ’; } };
struct X {

E
Objectives &
Outlines
explicit X(int i) { cout << "X(int)" << ’ ’; } // C++03 & C++11
explicit operator int() const { cout << "X::operator int()" << ’ ’; return 0; } // C++11 only

T
=default / explicit operator Y() const { cout << "X::operator Y()" << ’ ’; return Y("ppd"); } // C++11 only
=delete
};

P
Control of default void fx(const X&) { cout << "fx()" << ’ ’; } // checker function for conversion to X
move and copy
void fi(int) { cout << "fi()" << ’ ’; } // checker function for conversion to int
Compiler Rules
void fy(const Y&) { cout << "fy()" << ’ ’; } // checker function for conversion to Y

N
User Guidelines
int main() { int i { 5 }; X x { 1 }; // X(int)
Delegating fx(i); // X(int) fx(): error with explicit X::X(int)
Constructors
fx(static_cast<X>(i)); // X(int) fx()
In-class Init. fi(x); // X::operator int() fi(): error with explicit X::operator int()
Inheriting fi(static_cast<int>(x)); // X::operator int() fi()
Constructors fy(x); // X::operator Y() Y(string) fy(): error with explicit X::operator Y()
Override Controls
fy(static_cast<Y>(x)); // X::operator Y() Y(string) fy()
override
}
final
• explicit constructors have been available in C++03
explicit
Conversion
• explicit conversion operators are now available in C++11
bool • This makes conversion more type safe in C++11
Module Summary
• For casting between unrelated types recap Module 26 & Module 33
Programming in Modern C++ Partha Pratim Das M54.31
explicit Behavior Example Post-Recording
struct A { // converting ctor & operator struct B { // explicit converting ctor & operator
Module M54
A(int) { } explicit B(int) { }
A(int, int) { } // C++11 explicit B(int, int) { }

L
Partha Pratim
Das operator bool() const explicit operator bool() const
{ return true; } { return true; }

E
Objectives &
Outlines
}; };
int main() {

T
=default / A a1 = 1; // OK: copy-initialization selects A::A(int)
=delete
A a2(2); // OK: direct-initialization selects A::A(int)

P
Control of default A a3 {4, 5}; // OK: direct-list-initialization selects A::A(int, int)
move and copy
A a4 = {4, 5}; // OK: copy-list-initialization selects A::A(int, int)
Compiler Rules
A a5 = (A)1; // OK: explicit cast performs static_cast

N
User Guidelines
if (a1); // OK: A::operator bool()
Delegating bool na1 = a1; // OK: copy-initialization selects A::operator bool()
Constructors
bool na2 = static_cast<bool>(a1); // OK: static_cast performs direct-initialization
In-class Init.

Inheriting // B b1 = 1; // error: copy-initialization does not consider B::B(int)


Constructors B b2(2); // OK: direct-initialization selects B::B(int)
Override Controls
B b3 {4, 5}; // OK: direct-list-initialization selects B::B(int, int)
override
// B b4 = {4, 5}; // error: copy-list-initialization does not consider B::B(int,int)
final B b5 = (B)1; // OK: explicit cast performs static_cast
if (b2); // OK: B::operator bool()
explicit
Conversion // bool nb1 = b2; // error: copy-initialization does not consider B::operator bool()
bool bool nb2 = static_cast<bool>(b2); // OK: static_cast performs direct-initialization
}
Module Summary
Programming in Modern C++ Partha Pratim Das M54.32
explicit Conversion Operators: bool

Module M54 • explicit operator bool functions treated specially


• Implicit use okay when safe (that is, in contextual conversions):

L
Partha Pratim
Das

E
Objectives & #include <iostream>
Outlines using namespace std;

T
=default /
=delete class X { int *ptr; public:
explicit X(int *ptr = nullptr): ptr(ptr) { }

P
Control of default
move and copy explicit operator bool() const { cout << "X::operator bool()" << ’ ’; return nullptr == ptr; }
Compiler Rules };
int main() { X x1; X x2(new int(5));

N
User Guidelines

Delegating
// contextual conversions - permitted in spite of explicit
Constructors if (x1) cout << "NULL" << endl; // X::operator bool() NULL
cout << (x2? "NULL": "not-NULL") << endl; // X::operator bool() not-NULL
In-class Init.

Inheriting // non-contextual conversions - permitted only on absence of explicit


Constructors
cout << (x1 == x2? "Equal": "not-Equal") << endl;
Override Controls // Without explicit: x1 and x2 are implicitly converted to bool and compared by bool::operator==
override // X::operator bool() X::operator bool() not-Equal
final // With explicit: implicit conversion of x1 and x2 to bool are disallowed and hence operator== fails
explicit // error: no match for operator== (operand types are X and X)
Conversion }
bool

Module Summary
Programming in Modern C++ Partha Pratim Das M54.33
Module Summary

Module M54

• Introducing several class features in C++11 with examples

L
Partha Pratim
Das
• Explained how these features enhance OOP, generic programming, readability,

E
Objectives &
Outlines type-safety, and performance in C++11

T
=default /
=delete

P
Control of default
move and copy
Compiler Rules

N
User Guidelines

Delegating
Constructors

In-class Init.

Inheriting
Constructors

Override Controls
override
final
explicit
Conversion
bool

Module Summary
Programming in Modern C++ Partha Pratim Das M54.34

You might also like