const的用法文字说明都来自《C++编程思想》,这本书买了很久,一直都没有看。因为太厚,把它当工具书还行。一些代码只是随意写的,记录一下,留个脚印
要使用const 而非#define。用const来代替#define
#define把定义放到头文件中,我们同样也可以把const放到头文件中。
const定义必须给初值,除非用extern做声明的。
看下列代码:
我没有给初值,就报错了。
用extern const int i; 就不会报错 因为extern关键字说明它是一个外部的变量。这里只是声明。
现在把const int i= 100; 放到一个单独的文件中Test1.h
在main.cpp文件中
如果没有包含头文件,就会提示错误
现在把头文件包含上就正确了。
现在在Test1.h中把const int i=100; 改成 extern const int i=100;
这个时候就会报多重定义的错误。
Const 默认是内部连接的,所以不能再一个文件中定义const 在另一个文件中用extern 来引用。为了使用const成为外部连接以便让另外一个文件可以对他引用,必须明确的把他定义成extern。
这个时候我在main.cpp文件中需要引用i,则不能包含头文件,可以用。
extern const int i;
指向const的指针
定义一个指针的技巧是在标识符的开始处读它并从里向外读。Const 修饰 “最靠近”它的那个。
const int * p; 从标识符开始,是这样读:u是一个指针,它指向一个const int。这个时候它并不是一个const 变量,所以可以不初始化也不会出问题。
编译没有错误。
如果想要指针本身不变,很多人想当然的这样定义。
int const * p;
错误读法: p是一个指向int 的const 指针
正确读法:p是一个指向恰好是cont的int的普通指针。 (摘自《C++编程思想》)
这个和上面的const int * p;是同一个意思,这个容易混淆
使指针本身成为一个const指针,必须把const表明的部分放在*的右边
int d =1;
int * const w = &d;
w是一个指针,这个指针是指向int的const指针。
因为指针本身现在是const指针,编译器要求给他一个初值。
这个和之前定义const 变量没有给初值报同样错误。
const int * const x = &d; 指针和对象都不能改变
赋值和类型检查
可以把一个非const对象的地址赋值给const指针,但是不能把一个const对象地址赋值给一个非const指针。
函数参数和返回值
void f(const T t) ;
const 的含义是t不能被在函数里面修改。如果T是值传递就没多大意义,因为此时会生成一个副本。
void f(const T & t); 这个时候就能充分体现用处了。T不能被修改。
const int g(); 此时和上面类似,如果返回的是一个值类型,感觉意义不大,但是如果在类中,返回的是成员变量之类的。那就比较有意义。
如果一个函数按值返回一个类对象为const时,那么这个函数的返回值不能是左值。因为是const 所以不能修改。
如果返回的是指针或者引用,调用者就可以获得这个指针和应用来改变对象,如果不想调用者来改变你的对象,可以在前面加上const。这样就组织调用者修改。
const 用于class的两种方法
在类中定义const变量
class IntArray
{
public:
IntArray(int size);
virtual ~IntArray();
public:
void setValue(int index,int value);
int getValue(int index) const;
void printfAll()const;
private:
const int arraySize;
int* array;
private:
IntArray(const IntArray & arr);
IntArray &operator=(const IntArray & arr);
};
#include <iostream>
IntArray::IntArray(int size):arraySize(size)
{
array = new int[arraySize];
}
IntArray::~IntArray()
{
delete [] array;
}
void IntArray::setValue(int index, int value)
{
array[index] = value;
}
int IntArray::getValue(int index) const
{
return array[index];
}
void IntArray::printfAll() const
{
for(int i=0;i<arraySize;i++)
{
std::cout<<i<<" "<<getValue(i)<<std::endl;
}
}
const成员变量只能在构造函数初始化列表中初始化。
在函数后面加入const 证明此函数并没有改变成员变量的数据,可以在const对象中使用。
如果想要在一个const函数中类的成员被修改,可以在成员变量前面加mutable关键字。
class B
{
public:
B();
~B();
public:
int getIValuePlus() const;
int getJValuePlus() const;
private:
mutable int i;
int j;
};
B::B()
{
}
B::~B()
{
}
int B::getIValuePlus() const
{
i++;
return i;
}
int B::getJValuePlus() const
{
j++;
return j;
}
这个时候会报错。
但是改变i的值不会报错。