在“函数参数”中通过const类型在派生类中使用不同函数参数的虚函数会破坏虚函数吗? [重复]

问题描述 投票:1回答:5

一位C ++专家告诉我,在派生类中用const改变函数参数类型会破坏虚拟调用机制。

我尝试了一个简单的程序(原谅非标准代码,纯粹是为了测试而编写),否则就证明了这一点。函数参数按const值改变不会破坏虚拟机制,

是否有任何原因和文档指出这种行为?

VS 2012编译器和最新的g ++编译器注意到了行为。

#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;
}

输出:

base
derived
derived testx = 10
dest derived
dest base
c++ inheritance
5个回答
4
投票

顶级cv-qualifier不是函数签名的一部分,它们被简单地忽略。

[dcl.fct]/5

生成参数类型列表后,在形成函数类型时,将删除修改参数类型的任何顶级cv限定符。


5
投票

void test(int)!= void test(int) const并将“打破”虚拟电话。 和void test(int&)!= void test(const int&)并将“打破”虚拟通话。

void test(int)是与void test(const int)相同的声明,不会“打破”虚拟电话。


4
投票

你的C++ guru是错的(如果你理解它们,大师倾向于用神秘的信息说话)。参数类型本身的Const-qualifier根本不是函数签名的一部分。

例如,void foo(int* const );void foo(int* )没有什么不同。请注意,它与间接对象的const限定不同,例如void foo(const int* )void foo(int* )不同。

在您的特定情况下,void test(int x)void test(int const x)相同


3
投票

相当于std :: decay发生在函数的参数类型中。 (它实际上是相反的,std :: decay是在函数参数之后建模的。)

最外面的const将从签名中删除。通过最外层,将类型视为由不同类型组成的信封。指向const int的指针与指向int的指针的类型不同,并且将导致不同的函数签名。 (使用指针,您可以将指针本身视为外部事物,它指向的是“内部”而不是修改。)

  • const int - 变成int
  • int *没有变化,仍然是int *
  • const int *没有变化,仍然是const int * - const在int上,而不是指针,只有最外面的const被删除
  • int const *没有变化,仍然是int const * - const在int上,而不是指针,只有最外面的const被删除。 (注意,这与const int *的含义完全相同)
  • int * const - 对int *的更改 - 因为const限定了最外面的指针
  • int * const * const成为int * const * - 外部const被删除在外部指针上,内部const不会被丢弃在内部指针上。
  • const int * const * const成为const int * const * - 外部const被删除在外部指针上,内部const不会被丢弃在内部指针上,而const也保留在内部指针上
  • MyTemplate<const T> - 保持不变,仍然是MyTemplate<const T>,因为const不在外部类型上,而是依赖于模板参数

所以是的,const确实会影响类型,但不会像你尝试过的那样简单。仅当它包含在类型内部时,不会影响最外层类型。

如果您从右到左阅读类型,它可以提供帮助。如果类型说明符中最右边的东西是const,它总是被删除(例如int * const)。如果最左边的东西是const,那么只有在它符合条件的东西是类型中最右边的东西时才会被删除(例如const int,最左边的东西是const,它影响右边的int,右边的int是最右边的类型中的东西。)(例2:const * int没有丢弃,因为最左边的const修改了它右边的东西,这不是该类型中最右边的东西。)


1
投票

他是对的。刚看到警告就找到了。

在这种情况下:VS2008之前的编译器会在这种情况下破坏虚拟机制。

后来编译器发出警告C4373:虚函数覆盖'%$ pS',当参数仅由const / volatile限定符不同时,编译器的先前版本没有覆盖

在这里找到了https://msdn.microsoft.com/en-us/library/bb384874.aspx的文档

© www.soinside.com 2019 - 2024. All rights reserved.