[以下所有内容均使用Visual Studio 2008 SP1进行了测试]
在C++中,参数类型的const限定不影响函数的类型(8.3.5/3:"删除修改参数类型的任何cv限定符")
因此,例如,在以下类层次结构中,Derived::Foo覆盖Base::Foo:
struct Base
{
virtual void Foo(const int i) { }
};
struct Derived : Base
{
virtual void Foo(int i) { }
};
Run Code Online (Sandbox Code Playgroud)
在C++/CLI中考虑类似的层次结构:
ref class Base abstract
{
public:
virtual void Foo(const int) = 0;
};
ref class Derived : public Base
{
public:
virtual void Foo(int i) override { }
};
Run Code Online (Sandbox Code Playgroud)
如果我然后创建一个实例Derived:
int main(array<System::String ^> ^args)
{
Derived^ d = gcnew Derived;
}
Run Code Online (Sandbox Code Playgroud)
它编译没有错误或警告.当我运行它时,它会抛出以下异常然后终止:
ClrVirtualTest.exe中发生了未处理的"System.TypeLoadException"类型异常
附加信息:'Derived'类型中的方法'Foo'...没有实现. …
来自C++ Primer第5版,它说:
int f(int){ /* can write to parameter */}
int f(const int){ /* cannot write to parameter */}
Run Code Online (Sandbox Code Playgroud)
这两个功能难以区分.但是如您所知,这两个函数在更新参数方面确实存在差异.
有人可以向我解释一下吗?
编辑
我想我没有很好地解释我的问题.我真正关心的是为什么C++不允许这两个函数同时作为不同的函数,因为它们在"是否可以写入参数"方面确实不同.直观地说,应该是!
编辑传递值
的性质实际上是通过将参数值复制到参数值来传递的.即使对于复制值为地址的引用和指针也是如此.从来电者的角度来看,无论是常量还是非常量传递给函数不会影响复制到参数(当然类型)值.复制对象时
,顶级const和低级const之间的区别很重要.更具体地说,顶级const(不是
低的const)复制对象时会被忽略,因为复制不会影响复制的对象.复制或复制的对象是否为const无关紧要.
因此对于呼叫者来说,区分它们是没有必要的.可能,从功能的角度来看,顶级const参数不会影响接口和/或功能的功能.这两个功能实际上完成了同样的事情.为什么要打扰实施两份?
码
class A
{
public:
void f(const int i);
};
void A::f(int i)
{
std::cout<<++i<<std::endl;
}
int main()
{
A a;
a.f(1);
}
Run Code Online (Sandbox Code Playgroud)
为什么编译器在这种情况下不会出错?为什么定义会覆盖常量参数?此外,当参数是类型时reference (&),编译器会抛出错误,但为什么不在这种情况下呢?
是否有任何编译器标志可以在这些提到的情况下启用警告?
我对编译器错误POV感兴趣.因为可以很容易地将声明(const)和定义(非常量)放在一起,但编译器仍然接受它.如果可以犯错误,最终会犯错误.当存在这样的差异时,为什么编译器不能抱怨.
尝试了stackeroverflow qn所以它让我思考为什么不重载该函数,我想出了一个稍微不同的代码,但它说该函数不能重载.我的问题是为什么?还是有另一种方式?
#include <iostream>
using std::cout;
class Test {
public:
Test(){ }
int foo (const int) const;
int foo (int );
};
int main ()
{
Test obj;
Test const obj1;
int variable=0;
do{
obj.foo(3); // Call the const function
obj.foo(variable); // Want to make it call the non const function
variable++;
usleep (2000000);
}while(1);
}
int Test::foo(int a)
{
cout<<"NON CONST"<<std::endl;
a++;
return a;
}
int Test::foo (const int a) const
{
cout<<"CONST"<<std::endl;
return a;
}
Run Code Online (Sandbox Code Playgroud) 一位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;
}
Run Code Online (Sandbox Code Playgroud)
输出:
base
derived
derived testx …Run Code Online (Sandbox Code Playgroud) c++ ×4
const ×2
.net ×1
c++-cli ×1
c++11 ×1
c++14 ×1
class ×1
constants ×1
function ×1
inheritance ×1
overloading ×1
signature ×1
visual-c++ ×1