C++ 中的 Const 说明






2.38/5 (11投票s)
本文说明了 C++ 中 const 的常见用法
介绍
一个 const
对象是不应该被修改的对象。以下是可能的用法
//file header.h
const int global_const_count = 7; // global const in header file
class CX
{
public:
CX();
const int foo(const int) const; //const member function with a
//const parameter and return a const
private:
const int member_const_count; //non-static const member
static const int static_member_const_count = 7; //static const member
};
//file source.cpp
#include "header.h"
const int CX::foo(const int) const //const member function
//implementation
{
const int i = 1; //local const
return i;
}
int main()
{
return 0;
}
Const
参数、const
返回值和局部 const
没有什么特别之处,只是具有语义约束。以下示例涵盖了其他 const
用法。
使用代码
头文件中的常量
//file header.h
static int global_count;
const int global_const_count = 7;
//file source1.cpp
#include "header.h"
int main()
{
return 0;
}
//file source2.cpp
#include "header.h"
如我们所见,source1.cpp 和 source2.cpp 都包含 global_const_count
的定义。C++ 中的 const
必须默认具有内部链接。也就是说,它仅在其定义的文件中可见,并且不能在链接时被其他翻译单元看到。但不会有两个 const
的实例。通常,C++ 编译器会避免为 const
创建存储空间,而是将其定义保存在其符号表中。
常量类成员数据
//file header.h
class CX
{
public:
CX();
private:
const int member_const_count;
static const int static_member_const_count = 7;
};
//file source.cpp
#include "header.h"
CX::CX()
: member_const_count(7)
{
}
int main()
{
return 0;
}
非静态 const
成员是对象生命周期内的常量。由于常量必须在创建时初始化,因此 const
成员必须在类成员初始化列表中初始化。但对于静态 const
成员,它属于类而不是某个实例。因此,我们不能像初始化非静态 const
成员那样初始化它。因此,我们必须在定义它的地方进行初始化。
常量类成员函数
//file header.h
class CX
{
public:
CX();
void increase();
int getCount() const;
private:
int member_ count;
};
//file source.cpp
#include <iostream>
#include "header.h"
CX::CX()
: member_count(0)
{
}
void CX::increase()
{
++member_count;
}
int CX::getCount() const
{
return member_count;
}
int main()
{
const CX cx;
//cx.increase(); //Error, cx can't be changed.
std::cout << cx.getCount() << std::endl;
return 0;
}
一个 const
成员函数保证它不会修改对象实例。因此,可以在 const
对象上合法地调用 const
成员函数,而对于普通成员函数则不行。没有 static const
成员函数。static
成员函数不属于任何对象,因此没有对象可以更改。
Mutable
如果由于某种原因我们想更改 const
对象的数据成员,例如缓存数据,我们可以使用关键字 mutable,如下例所示
//file header.h
class CX
{
public:
CX();
void increase();
int getCount() const;
private:
mutable int cache_data;
int member_count;
};
//file source.cpp
#include <iostream>
#include "header.h"
CX::CX()
: cache_data(0)
, member_count(0)
{
}
void CX::increase()
{
++member_count;
}
int CX::getCount() const
{
++cache_data;
return member_count;
}
int main()
{
const CX cx;
std::cout << cx.getCount() << std::endl;
return 0;
}
当调用 int CX::getCount() const
时,Cache_data
会被更改。但对用户来说是透明的,该对象是“逻辑常量
”。
Const_cast
我们可以使用 const_cast
来移除对象的 const
属性。但这样做在大多数情况下会带来麻烦。有趣的是,C++ 编译器会出于“历史原因”对字符数组执行转换。
//file header.h
class CX
{
public:
CX();
void increase();
int getCount() const;
private:
mutable int cache_data;
int member_count;
};
//file source.cpp
#include <iostream>
#include "header.h"
CX::CX()
: cache_data(0)
, member_count(0)
{
}
void CX::increase()
{
++member_count;
}
int CX::getCount() const
{
++cache_data;
return member_count;
}
const int ci = 10;
int main()
{
int* pi = const_cast<int*>(&ci);
//*pi = 9;//compile OK, runtime error. Change constant ci
const CX cx;
CX* px = const_cast<CX*>(&cx);
px->increase(); //The change won't be noticed because cx is excepted as const
std::cout << cx.getCount() << std::endl;
char* sz = "string"; //Compiler do casting
//sz[0] = 'c'; //runtime error
return 0;
}
要修改 string
,请先将其放入数组中
char sz[] = "string";
延伸阅读
- 参考 Bruce Eckel 的《C++ 2ed. Vol 1, Chapter 8. Constants》。
- 参考 Scott Meyers 的《Effective C++ 3rd. Item 3: Use const whenever possible》。
历史
- 2008/9/17 文章的初始创建