Virtual functions with varying of function paramet

2020-04-18 05:12发布

A C++ guru told that varying the function parameter type with const in derived class, will break the virtual call mechanism.

I tried a simple program ( forgive for non standard code, written purely for test) , which prove otherwise. The function parameter change by const value will not break the virtual mechanism,

Is there any reasons & documentation pointing to this behavior?

Behavior noted with VS 2012 compiler & latest g++ compiler.

#include <iostream>
using namespace std;


class Base
{
public:
Base(){ cout<<"base"<<endl;}
virtual ~Base(){ cout<<"dest base"<<endl;}
virtual void test(const int x){ cout << "base test"<<"x = " << x<<endl;}
};

class Derived : public Base
{
public:
Derived(){ cout<<"derived"<<endl;}
virtual ~Derived(){ cout<<"dest derived"<<endl;}
virtual void test(int x){ cout << "derived test"<<"x = " << x<<endl;}
};
int main() {

    Base *b = new Derived();
    b->test(10);
    delete b;
    return 0;
}

output:

base
derived
derived testx = 10
dest derived
dest base

5条回答
淡お忘
2楼-- · 2020-04-18 05:43

void test(int) != void test(int) const and would "break" virtual call.
and void test(int&) != void test(const int&) and would "break" virtual call.

void test(int) is the same declaration than void test(const int) and won't "break" virtual call.

查看更多
疯言疯语
3楼-- · 2020-04-18 05:43

He was right.just found it by seeing the warning.

In this case : Compilers before VS2008 would break the virtual mechanism in this case.

Later compilers it gives warning C4373: virtual function overrides '%$pS', previous versions of the compiler did not override when parameters only differed by const/volatile qualifiers

found the documentation here https://msdn.microsoft.com/en-us/library/bb384874.aspx

查看更多
闹够了就滚
4楼-- · 2020-04-18 05:55

Your C++ guru is wrong (provided you understood them, gurus tend to talk in cryptic messages). Const-qualifier on the argument type itself is not a part of a function signature at all.

For example, void foo(int* const ); is no different from void foo(int* ). Please note, it is not the same as const qualification of the indirect object, like void foo(const int* ) is different from void foo(int* ).

In your particular case, void test(int x) is the same as void test(int const x)

查看更多
疯言疯语
5楼-- · 2020-04-18 06:03

The equivalent of std::decay happens to argument types for functions. (It's actually the reverse, std::decay is modeled after what functions arguments do.)

The outermost const will be dropped from the signature. By outermost, think of types as envelopes composed over different types. A pointer to const int is a different type than a pointer to int, and will result in a different function signature. (With a pointer, you can think of the pointer itself as the outer thing, and what it points to is "inner" and not modified.)

  • const int - becomes just int
  • int * is unchanged and remains int *
  • const int * is unchanged and remains const int * - const is on the int, not the pointer, and only the outermost const is dropped
  • int const * is unchanged and remains int const * - const is on the int, not the pointer, and only the outermost const is dropped. (Note, this is 100% identical in meaning as const int *)

  • int * const - changes to int * - because const qualifies the outermost pointer

  • int * const * const becomes int * const * - outer const is dropped on outer pointer, inner const is not dropped on the inner pointer.
  • const int * const * const becomes const int * const * - outer const is dropped on outer pointer, inner const is not dropped on the inner pointer, and const is also kept on the internal-most int
  • MyTemplate<const T> - unchanged, remains MyTemplate<const T>, because the const isn't on the outer type, but nestled in a template parameter

So yes, const does affect type, but not in the simple case like you tried. Only when it's contained inside of a type, not affecting the outermost type.

If you read types from right-to-left it can help. If the rightmost thing in a type specifier is a const, it is always dropped (example int * const). If the leftmost thing is const, it is only dropped if the thing it is qualifying is the rightmost thing in the type (example const int, the leftmost thing is const and it affects the int to its right AND the int to its right is the rightmost thing in the type.) (example 2: const * int not dropped, because leftmost const modifies the thing to its right that is not the rightmost thing in the type.)

查看更多
家丑人穷心不美
6楼-- · 2020-04-18 06:10

The top level cv-qualifier is not part of function signature, they are simply ignored.

[dcl.fct]/5

After producing the list of parameter types, any top-level cv-qualifiers modifying a parameter type are deleted when forming the function type.

查看更多
登录 后发表回答