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

时间:2018-04-18 18:32:25

标签: c++ inheritance

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

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

有什么理由吗?文档指向这种行为?

VS 2012编译器和&amp ;;最新的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

5 个答案:

答案 0 :(得分:5)

void test(int)!= void test(int) const并且&#34;打破&#34;虚拟电话。
void test(int&)!= void test(const int&)并且&#34;打破&#34;虚拟电话。

void test(int)void test(const int)的声明相同,并且赢得了&#34;#34;打破&#34;虚拟电话。

答案 1 :(得分:4)

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

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

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

相同

答案 2 :(得分:4)

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

[dcl.fct]/5

  

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

答案 3 :(得分:3)

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

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

  • const int - 变为 int
  • int * 未更改,仍为 int *
  • const int * 保持不变并且仍然是 const int * - const在int上,而不是指针,只有最外面的const被删除< / LI>
  • 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不在外部类型上,而是嵌套在模板参数中< / LI>

所以是的,const确实会影响类型,但不会像你尝试过的那样简单。只有当它包含在一个类型中时,才会影响最外面的类型。

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

答案 4 :(得分:1)

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

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

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

在此处找到了文档https://msdn.microsoft.com/en-us/library/bb384874.aspx