Article 12 Add an override declaration for a function intended to override

Add an override declaration for a function intended to override

class Base{
public:
    virtual void doWork();		//Virtual function in base class
};

class Derived : public Base{
public:
    virtual void doWork();		//Rewritten Base::dowork
};

std::unique_ptr<Base> upb = std::make_unique<Derived>();	//Create a base class pointer to a derived class object

upb->doWork();			//Call doWork through base class pointer
						//The result is that the derived class function is called

If the rewriting action really occurs, the following requirements must be met:

  • The function in the base class must be a virtual function
  • Function names in base and derived classes must be exactly the same (except destructors)
  • Function parameter types in base and derived classes must be identical
  • Function return values and exception specifications in base and derived classes must be compatible
  • Function reference modifiers in base and derived classes must be identical
    • Function reference modifiers are used to restrict member functions to be used only for left or right values. Member functions with reference modifiers do not have to be virtual functions.
class Widget{
public:
    void doWork() &;		//This version of doWork is only called when * this is an lvalue
    
    void doWork() &&;		//This version of doWork is only called when * this is an R-value
};

Widget makeWidget();		//Factory function

Widget w;				//Normal object (lvalue)

w.doWork();				//Call Widget::doWork with an lvalue
						//Widget:: dowork&

makeWidget().doWork();	//Call Widget::doWork with right value
						//Widget:: dowork&&

If the virtual function in the base class has a reference modifier, the derived class must also have the same reference modifier to rewrite the function. If not, these declared functions still exist in the derived class, but they do not overwrite any functions in the base class.

C++11 provides a method to explicitly indicate that the function in the derived class is to rewrite the version of the base class and add an override declaration to it.

class Base{
public:
    virtual void mf1() const;
    virtual void mf2(int x);
    virtual void mf3() &;
    virtual void mf4() const;
};

class Derived : public Base{
public:
    virtual void mf1() const override;
    virtual void mf2(int x) override;
    virtual void mf3() & override;
    virtual void mf4() const override;
};

Two contextual keywords in C++11: final and override. Their feature is that the language retains these two keywords, but only in a specific context. In the case of override, it is reserved only when it appears at the end of the member function declaration. This means that if you have some legacy code in which the name override has been used, you don't have to change the name in order to upgrade to C++11.

If we want to write a function that only accepts the passed in lvalue arguments, we will declare a non const lvalue reference parameter:

void doSomething(Widget& w);		//Only Widget types with lvalues are accepted

If we want to write a function that accepts only the right valued arguments passed in,

void doSomething(Widget&& w);		//Only Widget types with right values are accepted

The function of member function reference modifier is to add some differentiation to the object that initiates the member function call, that is, * this. This is the same as adding a const at the end of the member function declaration: the latter indicates that the object initiating the member function call, * this, should be const.

class Widget{
public:
    using DataType = std::vector<double>;
    
    DataType& data() &			//For an lvalue type, returns an lvalue
    { return values; }
    
    DataType data() &&
    { return std::move(values); } 	//For Widget type, return the right value

private:
    DataType values;
};

Overloaded version of lvalue reference type, which returns lvalue reference (i.e. an lvalue); The overloaded version of the R-value reference type returns a temporary object (that is, an R-value).

//Factory function to create Widget type object
Widget makeWidget();

Widget w;

auto vals1 = w.data();		//Call the lvalue overloaded version of Widget::data
							//vals1 uses copy structure to complete initialization

auto vals2 = makeWidget().data();	//Call the right value overloaded version of Widget::data
									//vals2 uses the mobile constructor to complete the initialization

Key points shorthand

  • Add override declaration for functions intended to override
  • Member function reference modifiers make it possible to distinguish the processing of l-valued and r-valued objects

Added by chinni_77 on Thu, 10 Feb 2022 08:17:16 +0200