一提到到const 关键字,我们首先想到的可能是const常量。
但const的功能可不仅仅局限于此,它可以修饰函数参数,返回值,甚至函数的定义体。
const是constant的缩写,“恒定不变”的意思。
但const的功能可不仅仅局限于此,它可以修饰函数参数,返回值,甚至函数的定义体。
const是constant的缩写,“恒定不变”的意思。
被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。
下面我们讲一下以下三种情况:
1.const修饰函数的参数
2.const修饰函数的返回值
3.const修饰成员函数
1.const修饰函数的参数
防止传入的参数代表的内容在函数体内被改变,注意仅仅对指针和引用有意义。
如果是 按值传递,传给参数的仅仅是实参的副本,即使在函数体内改变了形参,实参也不会得到影响。
防止传入的参数代表的内容在函数体内被改变,注意仅仅对指针和引用有意义。
如果是 按值传递,传给参数的仅仅是实参的副本,即使在函数体内改变了形参,实参也不会得到影响。
1.1 参数按“值传递”
代码块:
代码块:
int func(const int x)
{
//x += 10;//报错,表达式必须是可修改的左值
return x;
}
分析:输入的参数采用“值传递”,函数将自动缠身临时变量用于复制该参数,将在函数调用结束后自动销毁,所以无需保护。
1.2 参数按“指针传递”
代码块:
分析:参数按指针传递,函数将对const修饰的指针进行保护,防止被修改
代码块:
char* Strcpy(char*dst, const char* src)//src用const修饰可以防止意外地改变指针
{
strcpy(dst, src);//把src复制拷贝给dst
//strcpy(src, dst);//系统报错
return src;
}
分析:参数按指针传递,函数将对const修饰的指针进行保护,防止被修改
1.3 非内部数据类型的参数
对于非内部数据类型,如果采用“按值传递”,在函数体内,将会产生这个类型的临时对象用作实参的拷贝。
临时对象的产生,必然会调用临时对象的构造函数和析构函数,效率将会大大下降。
临时对象的产生,必然会调用临时对象的构造函数和析构函数,效率将会大大下降。
那么该如何去提高它的效率呢?
最有效的方法就是采用
“引用传递”
引用其实就是实参的别名,它和实参的内存地址相同,引用的改变将会引起外部实参的改变。
引用其实就是实参的别名,它和实参的内存地址相同,引用的改变将会引起外部实参的改变。
代码块:
class base
{
public:base(int x = 1)
:b(x)
{}
void operator= (const base& BB)//这里的BB是B的引用,加了const保护
{
b = BB.b;//赋值操作
}
int b;
};
int main()
{
base B(42);
base B1;
B1.operator= (B);
cout <<"b="<<B1.b << endl;
system("pause");
return 0;
}
分析:“引用传递”不需要产生临时对象,所以也就不存在构造析构函数的问题,但是有可能会改变外部的实参,所以在operator=函数中参数前面加了const保护,防止外部实参被有意无意的改变。
2.const修饰函数的返回值
2.1 如果函数的返回值是一个指针的话,加上const修饰。
即表示该指针指向的内容不能被改变,且只能用const修饰的同类型指针变量接收。
即表示该指针指向的内容不能被改变,且只能用const修饰的同类型指针变量接收。
代码块:
const char* Strcpy(char*dst, const char* src)
{
strcpy(dst, src);
return dst;
}
int main()
{
char* msg = "abcdefg";
char msg1[20];
const char* msg2 = Strcpy(msg1, msg);//msg2不用const修饰的话,将会报错。
system("pause");
return 0;
}
2.2 如果函数的返回值是“引用”的话,加上const修饰。
这种方式一般出现在类的赋值运算函数中。比如实现日期类的operator+=()函数。
这种方式一般出现在类的赋值运算函数中。比如实现日期类的operator+=()函数。
3.const修饰成员函数
我们都知道每个类的成员函数参数都有一个隐含的this指针,若在成员函数后面加const
则表明const修饰的是this指针所指向的对象,也就是保证调用这个const成员函数的对象的数据成员在函数内不会被改变。
若不慎修改,编译器将会报错。
提高了程序的健壮性。
则表明const修饰的是this指针所指向的对象,也就是保证调用这个const成员函数的对象的数据成员在函数内不会被改变。
若不慎修改,编译器将会报错。
提高了程序的健壮性。
class base
{
public:base(int x = 1)
:b(x)
{}
void func (void)const//const成员函数 这里相当于const base *this
{
//b++;//表达式必须是可修改的左值
cout << "func()::b="<<this->b << endl;
}
void dis()//普通成员函数
{
b++;
cout <<"dis()::b=" << this->b << endl;
}
int b;
};
int main()
{
base B(42);//非const对象
const base B1(24);//const类型对象
B.func();//非const对象调用const成员函数
B.dis();//非const对象调用普通成员函数
B1.func();// const对象调用const成员函数
//B1.dis();//报错,对象包含与成员函数的类型限定符不兼容
system("pause");
return 0;
}
结论:
1. const对象只能访问const成员函数,而非const对象可以访问任意的成员函数,包括const成员函数。
1. const对象只能访问const成员函数,而非const对象可以访问任意的成员函数,包括const成员函数。
2. const对象的成员是不可修改的。
3.const成员函数不可以修改对象的数据。