specifier override to indicate intention to override
Assume that you want override the Fish::Swim in Derived class but with a slightly different signature - one using const inserted unintentionally like the following
1 | class Tuna: public Fish |
this function actually does not override Fish::Swim(). Therefore, override supplies a powerful way of expressing the explicit intention to override a base class virtual function, thereby getting the compiler to check whether:
- the base class function is virtual
- the signature of the base class virtual function exactly matches that of the
Derivedclass function declared to override.
using final to prevent function overriding
A class declared as final cannot be used as a base class, similarly, a virtual function declared as final cannot be overridden in a derived class.
:
1 | class Tuna: public Fish |
class Tuna in this snippet can be inherited from, but Swim() cannot be overridden any further.
virtual copy constructors
c++ does not allow usage of virtual copy constructors.
Having said that, there is a nice workaround in the form of defining your own clone function that allow you to do that:
1 | class Fish |
the this pointer
The this pointer is a pointer accessible only within the nonstatic member functions of a class, struct, union type. It points to the object for which the member function is called.
:
1 | this |
The this pointer's type can be modified in the function declaration by keywords const and volatile. To declare a function that has either of these attributes, add the keywords after the function argument list.
consider an example:
1 | class Point |
The preceding code declares a member function X(), in which the this is treated as a const pointer to a const object.
Go ahead with virtual function clone, it's a simulated virtual copy constructor that needs to be explicitly invoked.
e.g. A clone function as a simulated virtual copy constructor demolist11_9
1 |
|
output
1 | new Tuna(*this) 0x55ad513c1320 |
Comparing line 17 with line 65 and line 66, the address of new Tuna is expected to be allocated, whereas, the three have difference store address as the output line 1,2,3 demonstrates. myFish[0] get a address by using new Tuna() in line 57 before we call myFish->Clone() in line 64 of main. Therefore, myNewFish() is allocated to a address as well while calling. Line 18 can be interpreted as:
1 | Base* X= new Base; |
as the preceding snippet demonstrates, argument Y is a representation of myNewFish(), and X is the transit.
Additionally
[Why we can do : Base base = new Derived; while we can not do Derived derived = new Base?]
Remember mark functions in derived classes that are intended to override base functionality using keyword overridden.
QAbstract base classes and pure virtual function.
- a base class that cannot be instantiated is called an
abstract baseclass. It fullfils only one purpose, that of being derived from.- e.g.
virtual void BaseFunc () = 0;
: Given an inheritance hierarchy, do I need to use the keyword virtual on all declarations of a virtual function or just in the base class.
: It is enough to declare a function as virtual once, but that declaration has to be in the base class. As long as a class has at least one pure virtual function, it remains an abstract base class(ABC) irrespective of the presence or absence of other fully defined functions or parameters.
exercise
Bug busters
Q:what is the problem in the following code:
1 | class Vehicle |
: doesn't have a virtual destructor. That can cause only one(car or vehicle) destructor invoked when it goes out of scope. e.g.
1 | Vehicle* pMyRacer = new Car; |
In this case nonvirtual destructor would result in only ~Vehicle invoked.
Correction
1 | class Vehicle |