一位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
答案 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)
答案 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