1.const 修饰成员变量
int main()
{
int a1=3;
const int a2=a1; // a2 不可以修改
int * a3 = &a1;
const int * a4 = &a1; // (*a4)++ 不可以,a4++ 可以
int * const a5 = &a1; // (*a5)++ 不可以,a5++ 可以
// a5和上面的a4表示一样
int const * const a6 = &a1; ///(*a6)++,a6++ 都不可以
const int * const a7 = &a1; ///(*a7)++,a7++ 都不可以
return 0;
}
const修饰指针变量时:
只有一个const时
如果const 位于*左侧,表示指针所指数据是常量,不能通过解引用修改该数据;指针本身是变量,指针可以修改,即可以指向其他的内存单元。如果const位于*右侧,表示指针本身是常量,不能指向其他内存地址;但是指针所指的数据可以通过解引用修改。
两个const
即 “ * ” 左右各一个,则表示指针和指针所指数据都不能修改。
2.const修饰函数参数
表示传递过来的参数在函数内不可以改变,与上面修饰变量时的性质相同。
eg:
void func(const int len)
{
len = 5; // 编译出错
}
程序中当我们调用这个函数时,编译会出错。
在类中声明变量为const类型,但是不可以初始化
const常量的初始化不可以在构造函数函数体内初始化,必须在构造函数初始化列表中初始化。
eg:
#include <iostream>
using namespace std;
class A
{
public:
A(int _a) : a(_a) {};
/*
A(int _a) // 编译发生错误
{
a = _a;
}
*/
void show()
{
cout << "_a = " << a << endl;
}
private:
const int a;
};
int main()
{
A a(100);
a.show();
}
为了让一个属于具体的一个对象的const变量,我们使用枚举让其值在整个类中都恒定不变。
eg:
class A
{
private:
enum {_a = 100};
public:
int array[_a];
};
枚举常量不会占据对象的存储空间,在编译时被全部求值.
但是,它隐含的数据对象类型为整形,不能表示其他类型。
必须在构造函数的初始化列表中有以下几种情况:
- 类的const常量
- 类的引用类型成员
- 没有默认构造函数的类的类型成员
- 如果类存在继承关系,派生类必须在其初始化列表中调用基类的构造函数
3.const成员函数
任何不修改数据成员的函数都应该声明为const类型。如果在编写const成员函数时,不慎修改了数据成员,或调用了其他非const成员函数,编译器就会指出错误。
eg:
class A
{
public:
void Ap1();
int Ap2();
int getcount() const;
private:
int num;
};
int A::getcount() const
{
num++; // 编译出错,企图修改数据成员
Ap2(); // 编译出错,企图调用非const函数
return num;
}
在同一个类中,是否可以仅通过const定义两个函数名字、参数、返回值完全相同的两个成员函数,用下面的实例来说明:
eg:
#include <iostream>
using namespace std;
class A
{
public:
A(int n) : num(n){}
void Ap()
{
cout << "not_count Ap()" << " : " << num << endl;
}
void Ap() const
{
cout << "count Ap()" << " : " << num << endl;
}
private:
int num;
};
int main()
{
A a(10);
a.Ap();
A const a1(25);
a1.Ap();
return 0;
}
结果:
not_count Ap() : 10
count Ap() : 25
从上述程序和结果可以看出:
同函数名、参数、返回值可以仅通过是否为const来定义为类的两个成员函数。在调用时,const对象调用const成员函数,非const对象调用非const成员函数。
虽然不可以在const函数中改变成员变量的值,但是如果在const函数中改变成员变量的值,则可以使用mutable这个关键字。
mutable关键字
mutalbe的中文意思是“可变的,易变的”,跟constant(既C++中的const)是反义词。在C++中,mutable也是为了突破const的限制而设置的。被mutable修饰的变量(mutable只能由于修饰类的非静态数据成员),将永远处于可变的状态,即使在一个const函数中。
假如类的成员函数不会改变对象的状态,那么这个成员函数一般会声明为const。但是,有时我们需要在const的函数里面修改一些跟类状态无关的数据成员,那么这个数据成员就应该用mutalbe来修饰。
看下面的例子:
eg:
#include <iostream>
using namespace std;
class A
{
public:
A(int n) : num(n){}
void Ap() const
{
num++;
cout << num << endl;
}
private:
mutable int num;
};
int main()
{
A const a(10);
a.Ap();
A const a1(25);
a1.Ap();
return 0;
}
结果:
11
26
从上述程序与结果,可知const修饰的函数中的成员变量已经改变,并且非const对象可以调用const函数。
但是,还有非const函数时,非const对象不可以调研那个const函数(否则,类的数据变量就会发生变化)。
问题:
当类中存在只有 是否为const 不同的两个函数时,const函数是否可以暂时调用那个非const函数?
是可以的。我们可以用const_cast将转化掉表达式的const性质
#include <iostream>
using namespace std;
class A
{
public:
A(int a) : _a(a){}
void print()
{
cout << "not_const print : " << _a << endl;
}
void print() const
{
cout << "const print : " << _a << endl;
}
private:
int _a;
};
int main()
{
A a(10);
a.print();
// const_cast<A> a.print(); // 编译报错,单纯用类不行,
const A *b1 = new A(20);
const_cast<A *> (b1)->print();
b1->print();
return 0;
}
结果:
not_const print :10
const print : 20
not_const print :20
const_cast用法:
class B{ public: void print();};
const B b;
const B *c;
- B b1 = const_cast<B&>(b);
- B *b2 = const_cast<B*>(&b);
- B &b3 = const_cast<B&>(b);
返回类型是const
const返回类型只有在修饰指针或引用是才有用。单凭const返回类型不可以重载。