您的位置:首页 > 编程语言 > C语言/C++

C++中的const

2013-05-03 20:53 288 查看
const告诉编译器它所约束的对象是不允许被修改的,它可以作用于任何作用域类的对象(包括类对象),函数参数和返回值,及成员函数本体,使用它可以在编译时及时发现错误。

1)const与指针

const可以修饰指针本身,也可以修饰指针所指的对象,或者限制指针与其所指对象都为const,如下:

const char* p = "hello";//non-const pointer, const data
char* const p = "hello"; //const pointer, non-const data
const char* const p = "hello"; //const pointer, const data


注意,const限制指针所指物不可修改时,有以下两种方式:

const char* p = "hello";
char const * p = "hello";


也就是说,const既可以位于数据类型前也可以位于数据类型后,但必须位于星号前,它们组合在一起用来修饰指针所指的对象。可以这样理解,星号前面的用来修饰被指物,星号

后面的用来修饰指针。

2)const与STL迭代器

STL迭代器与指针类似(难道不是一样的吗?),用const修饰迭代器就像声明指针为const一样,表示该迭代器不能指向不同的东西,如果要限制迭代器所指的对象不可修改,则需

要使用const_iterator,具体如下:

std::vector<int> v;
...
const std::vector<int>::iterator<int> iter = v.begin(); // iter是不能更改的,类似T* const
*iter++; //ok!
iter++; //error, iter是const常量

std::vector<int>::const_iterator<int> iter = v.beign(); //iter不是const,所指对象是const,不能更改
*iter++; //error!
iter++; //ok!


3)const修饰函数参数及返回值

对于函数声明:

const int operator*(const int& a, const int& b)
{
  return a*b;
}


它表示函数的参数和返回值都是不可以被修改的,所以下面的代码就是错误的:

int a = 3;
int b = 4;
int c = 5;
a*b = c; //a*b返回的是一个const常量,不可以修改


4)const与成员函数

a. 被const修饰的成员函数使得操作“const对象”成为可能,例如下面的代码编译就无法通过:

class Head
{
  public:
    Head(string s) { pText = s; }
    char& operator[](size_t pos)
    {
      return pText[pos];
    }
    private:
      string pText;
}

int main()
{
    const Head h1("Hello");
    cout<<h1[1]<<endl;     //成员函数operator[]不能操作const对象
}


此时可以添加const成员函数来操作const对象:

const char& operator[](std::size_t pos) const { return pText[pos]; }


b. 被const修饰的成员函数不改动任何非static成员变量,下面的情况除外:成员变量是一个指针类型,此时指针所指的地址不可以改变,但指针所指的对象却可以改变。比如将

上面代码中的成员变量pText改为char*类型,即声明如下:

char* pText;


同时令对应的const成员函数的返回值不再是const类型,具体修改如下:

char& operator[](std::size_t pos) const { return pText[pos]; }


那么下面const成员函数调用也是正确的:

const Head h2("Good");
char* p = &h2[0];
*p = 'J'; //此时pText所指向的字符串为“Jood”


这样的情况编译器能够通过是因为在const成员函数确实没有改变成员变量pText的值,只是改变了该值对应的变量。如果执意要在const成员函数中对成员变量进行赋值操作,那

么可以引入摆动场:mutable,它将释放在const成员函数中非static成员变量的不可改动性。

例如如下代码将通过编译:

class Head
{
  public:
     ...
    size_t length() const;

 private:
    char* pText;
    mutable size_t textLength;  //表示这些变量可能经常会被改动,即使在
    mutable bool LengthIsValid; //const成员函数里也有可能被修改
};

size_t Head::length()
{
  if(!LengthIsValid)
  {
    textLength = strlen(pText);
    LengthIsValid = true;
  }
}


5)const转型

如果两个重载函数只是在是否是常量性上有区别,要做的事几乎一样,那么可以通过将常量性转除来实现调用两次却只执行一次的功能,这样一来就避免了代码的重复,从而减

少编译时间,代码维护时间以及避免代码膨胀等问题。因为const成员函数的本意是不修改对象,而non-const成员函数却可以对对象做任意的修改,所以在const成员函数中调用

non-const是不合理也是不允许的,但是在non-const成员函数中调用const成员函数却是可行的,具体如下:

class Head
{
public:
    ...
    const char& operator[](std::size_t pos) const
    {
    return pText[pos];
    }
    char& operator[](std::size_t pos)
    {
      return const_cast<char&>(static_cast<const Head&>(*this)[pos]);
    }
}


上述代码中有两次转型操作,首先通过static_cast<const Head&>将类型为Head&的*this转为const Head&类型,从而调用const的成员函数,然后通过const_cast<char&>去掉const成员函数返回值的const属性。

切记:const成员函数不可以调用non-const成员函数。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: