C++ const常量成员函数
const的的用法太多了,常量成员函数就是曾经让我迷惑的用法之一,即在成员函数的参数列表之后加上const。
this 指针
在说常量成员函数之前,必须得详细知道this指针,以前我们知道不论C++还是java中,this都可以表示对象本身,事实如此,而在C++中更准确的定义是:
this是一个额外的隐式参数,用来访问当前对象,而它的本质是一个常量指针
常量指针(const pointer),区别于指向常量的指针(const to pointer),前者表示指针的值不能被修改(地址不变),后者表示指针所绑定的对象的值不能被修改,由于this就指向当前对象,我们不能用this在去绑定其他对象,因此他就是一个常量指针。
假设现在有一个类
class people
则this的类型是:
people *const
const成员函数
那么现在问题来了,const成员函数究竟是什么玩意?
上面提到,this指针是一个非常量版本的常量指针,那么当我们创建常量对象的时候,不能把this绑定到一个常量对象上——即不能使用一个常量对象调用普通函数。
代码:
class people{
public:
people(){}
people(int x) :score(x){}
~people(){}
int getScore(){ return score; }
private:
int score;
};
int main()
{
const people p1();
cout << p1.getScore() << endl;//error
system("pause");
return ;
}
这段代码编译器直接报错:
对象包含于成员函数不兼容类型的限定符。
这也就说明了普通指针(包括非常量指针和常量指针)无法绑定一个常量对象。简单来讲,下述语句无法成立:
const double pi=;
double* ptr1=π//error1
double* const ptr2=π//error2
const double* ptr1=π//ok1
const double* const ptr2=π//ok2
我们需要用一个指向常量的指针来绑定常量对象。
那么现在问题又来了,怎么使隐式调用的this指针变成指向常量的常量指针?
答案就是在成员函数的参数列表后面加入关键字const,例如上述示例中:
int getScore() const { return score; }
这样我们就可以使用常量对象调用
getScore()
方法了
class people{
public:
//...
int getScore() const{ return score; }
//...
};
int main()
{
const people p1();
cout << p1.getScore() << endl;//ok
system("pause");
return ;
}
这样就叫做常量成员函数(const member function),我们可以使用非常量对象调用常量成员函数,这样做是合法的,因为我们可以使用指向常量的指针来绑定一个非常量对象,例如,下述语句合法:
double pi = ;
const double * ptr=π
因此,下述使用也是合法:
class people{
public:
//...
int getScore() const{ return score; }
//...
};
int main()
{
people p2();
cout << p2.getScore() << endl;//ok
//...
}
—————–2016年5月29号更新—————–
关于const成员函数的补充
对于一个成员函数来说,它有一个隐藏的参数,来表示对象的地址,例如:
class Foo
{
public:
void hello(int a)
{
cout << "hello"+a<<endl;
}
};
//...
int main()
{
Foo foo;
int a=;
foo.hello(a);
//等价于
foo.hello(&foo,a);
}
从上述代码看出,这里相当于有一个该对象地址的隐式参数传递,也就是说,从函数声明的角度,这里应该是这个样子:
class Foo
{
public:
void hello(Foo* this ,int a)
{
cout << "hello"+a<<endl;
}
};
当我们给成员函数的声明后面加上const以后,例如:
void hello(int a) const
{
cout << "hello"+a<<endl;
}
这里就可以理解为有一个const的指针作为参数,如
void hello(const Foo * this,int a) const
{
cout << "hello"+a<<endl;
}
因为this是const的类型的,当然也就防止了成员函数对类中成员进行修改。
知道了这个东西,就能正确引导我们的使用。
比如说,假如有一个class
class A
{
//...
public:
void func1() const;
void func2();
}
我们在使用的时候可能有如下组合:
int main()
{
//...
A a1;
const a2;
a1.func1();
//等价于a1.func1(&a1);//ok
a1.func2();
//等价于a1.func2(&a1);//ok
a2.func1();
//等价于a2.func1(&a2);//ok
a2.func2();
//等价于a2.func2(&a2);//error
}
情况1,用const的指针绑定普通对象,可行,类似于:
int a =;
const int *pa=&a;
情况2,用普通指针绑定普通对象,可行,类似于:
int a=;
int *pa=&a;
情况3,用const指针绑定常量对象,可行,类似于:
const int a =;
const int *pa=&a;
情况4,用普通指针绑定const对象,不可行,类似于:
const int a =;
int *pa= &a;//error
参考:http://stackoverflow.com/questions/3141087/what-is-meant-with-const-at-end-of-function-declaration