Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I lose "constness" in the return type of an override virtual function?

Tags:

c++

The following code compiles and runs, and no warning is emitted by either gcc or clang:

#include <iostream>

struct Base {
    virtual ~Base() = default;
    virtual std::string const& get() = 0;
};

struct Derived: Base {
    virtual std::string& get() override { return m; }
    std::string m;
};

int main()
{
    Derived d;
    d.get() = "Hello, World";

    Base& b = d;
    std::cout << b.get() << "\n";
}

Is std::string& covariant with std::string const& then?

like image 344
Matthieu M. Avatar asked Oct 05 '16 08:10

Matthieu M.


People also ask

Can virtual function change return type?

The return type of an overriding virtual function may differ from the return type of the overridden virtual function. This overriding function would then be called a covariant virtual function. Suppose that B::f overrides the virtual function A::f .

Can you override a virtual function?

You can override virtual functions defined in a base class from the Visual Studio Properties window.

Do I need to override virtual functions?

It is not mandatory for the derived class to override (or re-define the virtual function), in that case, the base class version of the function is used.

What is the difference between virtual function and function overriding?

The virtual keyword is used to modify a method, property, indexer, or event declared in the base class and allow it to be overridden in the derived class. The override keyword is used to extend or modify a virtual/abstract method, property, indexer, or event of base class into a derived class.


1 Answers

Yes

This is specified in class.virtual, in the latest draft (n4606) we see:

§10.3 7/ The return type of an overriding function shall be either identical to the return type of the overridden function or covariant with the classes of the functions. If a function D::f overrides a function B::f, the return types of the functions are covariant if they satisfy the following criteria:

  • both are pointers to classes, both are lvalue references to classes, or both are rvalue references to classes111
  • the class in the return type of B::f is the same class as the class in the return type of D::f, or is an unambiguous and accessible direct or indirect base class of the class in the return type of D::f
  • both pointers or references have the same cv-qualification and the class type in the return type of D::f has the same cv-qualification as or less cv-qualification than the class type in the return type of B::f.

Specifically, the last point addresses exactly the case here: it is acceptable for an overriding type to lose the const and/or volatile qualifiers (it cannot, however, gain them).


Note: as mentioned by @george above, paragraph 8/ used to prevent this from working with incomplete class types, but this was since fixed.

like image 154
Matthieu M. Avatar answered Oct 31 '22 04:10

Matthieu M.