Home > Back-end >  I have Question about class overriding in C
I have Question about class overriding in C

Time:11-15

When I study about override keyword, I found some strange thing like below code.

#include <iostream>
template <class T> 
class A
{
    public: 
        virtual void some_function(const T a)
        {
            std::cout<<__PRETTY_FUNCTION__<<std::endl;
            std::cout<<"Base"<<std::endl;
        }
};
class Derived : public A<int*>
{
    public:
        virtual void some_function(const int* a)
        {
            std::cout<<__PRETTY_FUNCTION__<<std::endl;
            std::cout<<"Derived"<<std::endl;
        }
};
int main()
{
    A<int*>* p = new Derived;
    p->some_function(nullptr);

    delete p;
}  

When I first saw that code, I expected "Derived" to be called. But above code print result like below.

void A<T>::some_function(T) [with T = int*]

Base

But when I removed const keyword in the some_function that placed in Derived class,

class Derived : public A<int*>
{
    public:
        virtual void some_function(int* a)
        {
            std::cout<<__PRETTY_FUNCTION__<<std::endl;
            std::cout<<"Derived"<<std::endl;
        }
};

It print "Derived". Can you tell me why this is happening?

CodePudding user response:

The function prototypes are not the same. For T=int* const T a: a is a const pointer to an int, while const int *a is a pointer to an const int. For one the pointer is const, for the other the int is const.

int * const a would be the same as const T a, or you can make T=const int*.

https://godbolt.org/z/WEaEoGh58

Also important to note: When you derive from a class you must declare a virtual destructor.

A hint: when you use the keyword override on the derived function, you will get an error that you are not overriding the function: https://godbolt.org/z/o87GMrhsd

CodePudding user response:

At

const T a

const qualifier is interpreted as top-level cv-qualifier for T, so it is processed

T const a

thus if int* is set to T, parameter type becomes

int* const a

So, your Derived's function signature (it is called second level const qualifier)

const int* a

is different from Base's one. As a result, your Derived virtual function is not called.

In addition, C has the rule of "ignore top-level cv-qualifier from function signature". So, your Base's signature

int* const 

and if you give the type of

int* 

into Derived's signature, these two types signature are interpreted to be equivalent. As a result, your Derived virtual function is called correctly.


The following is a back-ground for your help. The type of

T*

has two component T and pointer and then

T* const

is called top-level cv-qualifier which is applied to *, and then

T const * 

is called second level cv-qualifier which is applied to T (equal to const T*). C ignore top-level cv-qualifier from signature. On the other hand, second level qualifier is included to signature. Therefore for example,

void f(int*) {}
void f(int* const){}

is failed to compile because of same signature by top-level cv-qualifier ignoring. In contrast,

void f(int*) {}
void f(int const * ){}

is compiled successfully by the difference of second level cv-qualifiers.

This is important to understand the behavior of virtual function calls. The reason is that the signature of derived virtual function and base's one must be identical to call it correctly.

  •  Tags:  
  • c
  • Related