65.9K
CodeProject 正在变化。 阅读更多。
Home

C++ 中的 Const 说明

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.38/5 (11投票s)

2008年9月17日

CPOL

2分钟阅读

viewsIcon

26430

本文说明了 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.cppsource2.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 文章的初始创建
© . All rights reserved.