深入探索C++类的const成员函数
const 成员变量的用法和普通 const 变量的用法相似,只需要在声明时加上 const 关键字。初始化 const 成员变量只有一种方法,就是通过构造函数的初始化列表。
const 成员函数可以使用类中的所有成员变量,但是不能修改它们的值,这种措施主要还是为了保护数据而设置的。const 成员函数也称为常成员函数。
我们通常将 get 函数设置为常成员函数。读取成员变量的函数的名字通常以get
开头,后跟成员变量的名字,所以通常将它们称为 get 函数。
(1)const 成员函数把 const 关键字放在函数的形参列表和函数体之间。比如
class A
{
void f() const {}
const int g()
{
return 2;
}
};
其中函数 f 是 const 成员函数,函数 g 只是一个返回类型为 const int 的函数。
(2)在类体外定义 const 成员函数时也必须同时指定 const 关键字。比如
class A
{
void f() const;
};
在类体外定义函数 f 的形式为
void A::f() const f{...};
(3)在 const 成员函数体内,数据成员相当于被 const 修饰,即 const 成员函数不能修改类的数据成员,但非类的数据成员则可以修改。
比如
class A
{
int a;
void f(int b) const
{
int c;
b = l;
c = 2;
a = l;
}
};
其中 a = 1;
是错误的,其他都是正确的。因为 b 和 c 不是类的数据成员。再比如
class A
{
int a;
void f() const
{
int* p = &a;
const int *pl = &a;
}
};
其中 const int *pl = &a;
是正确的,int* p = &a;
是错误的,因为指向非 const 的指针不能指向 const 常量,在 const 成员函数内部相当于被 const 修饰。
(4)在 const 成员函数体内,成员指针也相当于被 const 修饰,但 const 是修饰的指针本身也就是指针成员相当于 * const p
。因此在
const 成员函数体内能修改指针成员所指向的对象的值但不能改变指针成员本身的值,或者说指针成员是常量,但指向的值不是常量。比如
class A
{
public:
int a;
int *p;
void f() const
{
int b = l;
*p = 3;
p = &b;
}
};
其中 p = &b;
是错误的。注意:需要加一个构造函数初始化指针 p。
(5)const 成员函数可以与具有相同参数表的非 const 成员函数形成重载,在调用时,非 const 对象将调用非 const 成员函数,而 const 对象则只能调用 const 成员函数。比如 class A{void f(){}; void f() const{} };
,其中的两个函数 f 是重载关系,而非重定义;再比如const A ma; A mb;
,则 ma.f()
将调用 const 成员函数,mb.f()
将调用非 const 成员函数。
(6)const 成员函数不能调用非 const 成员函数。因为在const 成员函数内,调用类的成员时需要通过隐藏的 this 指针,而 const 成员函数的 this 指针类型为 const 类名 *const
,即既不能改变 this 指针本身的值,也不能改变 this 指针所指向的对象,因为无法保证非 const 成员函数不改变数据成员的值,所以const成员函数不能调用非 const 成员函数。
(7)注意:若使用强制转换去掉 this 的 const 性质,const 成员函数就可以调用非 const 成员函数了;同理,也可以在 const 成员函数内改变数据成员的值。比如
class A
{
public:
int a;
void g() {}
void f() const
{
((A* const)this)->g();
((A* const)this)->a=4;
}
};
正确,其中 ((A* const)this)
表示把 this 指针强制转换为 A* const
,即强制转换去掉了最前面的 const。
(8)注意:非成员函数不能把 const 关键字放在小括号之后,比如 void f()const{};
是错误的。
例子
class Student{
public:
Student(char *name, int age, float score);
void show();
//声明常成员函数
char *getname() const;
int getage() const;
float getscore() const;
private:
char *m_name;
int m_age;
float m_score;
};
Student::Student(char *name, int age, float score): m_name(name), m_age(age), m_score(score){ }
void Student::show(){
cout<<m_name<<"的年龄是"<<m_age<<",成绩是"<<m_score<<endl;
}
//定义常成员函数
char * Student::getname() const{
return m_name;
}
int Student::getage() const{
return m_age;
}
float Student::getscore() const{
return m_score;
}
该文章会更新,欢迎大家批评指正。
推荐一个零声学院免费公开课程,个人觉得老师讲得不错,
分享给大家:[Linux,Nginx,ZeroMQ,MySQL,Redis,
fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,
TCP/IP,协程,DPDK等技术内容,点击立即学习:
服务器课程:C++服务器