C++的那些事:const用法面面观

发表于:2014-5-05 09:54

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:☆Ronny丶    来源:51Testing软件测试网采编

  这里再强调一点,const只是给编译器看的,我们可以很轻松的骗过编译器,并看看编译器都做了什么:
  1 const int var = 42;
  2 int* p = (int*)&var;
  3 *p = 20;
  4 cout << var << endl;     //42
  5 cout << *p << endl;     //20
  我们在代码的第2行,用一个类型转换强制的,把一个非const指针指向了一个const对象。
  但是后面我们通过这个指针来修改这个值,却没有生效,原因呢?
  那是因为编译器在编译阶段发现var是一个常量,所以在编译目标代码时已经将var的地方都用42进行了替换。
  六、const与类
  其实类定义的对象,与普通的变量是一样的,用const修饰时,说明这个类是一个常量类对象,这个对象有下面2个特点:
  1)不能改变其成员变量(非mutalbe成员)
  2)不能调用其非const成员函数
  1 class AClass{
  2     public:
  3         int m_var;
  4         mutable int m_mutable_var;
  5         void setVar(int var){ m_var = var; }
  6         void printVar(){ cout << m_var; }
  7         void printVar_const()const { cout << m_var; }
  8     };
  9
  10     const AClass ac;
  11     ac.m_var = 20; // Error:ac是一个const类,不能修改成员变量
  12     ac.m_mutable_var = 42; // ok 可以修改mutable修饰的变量
  13     ac.setVar(20); // Error: ac不能调用非const成员函数,而且这个成员函数还修改了成员变量的值
  14     ac.printVar();// Error:ac不能调用非const成员函数
  15     ac.printVar_const(); // ok
  七、const与类的成员
  1,const成员变量
  const 成员变量指的是类中的成员变量为只读,不能够被修改(包括在类外部和类内部)。
  1)const 成员变量必须在类的构造函数初始化表达式中被初始化,即使在构造函数体内也不可以。
  2)静态 const 成员变量需要在类外部单独定义并初始化(可定义在头文件)
1 class constTestClass
2 {
3 public:
4     const int var;
5     static const int sci;
6 public:
7     constTestClass() :var(42){} // const成员变量必须在类的构造函数初始化列表中初始化
8 };
9 const int constTestClass::sci = 42; // static const成员变量需要在类外单独进行定义和初始化
  类对象的实例化过程可以理解为包含以下步骤:首先,开辟整个类对象的内存空间。之后,根据类成员情况,分配各个成员变量的内存空间,并通过构造函数的初始化列表进行初始化。最后,执行构造函数中的代码。由于 const 成员变量必须在定义(分配内存空间)时,就进行初始化。所以需要在够在函数的初始化列表中初始化。const成员在初始化之后,其值就不允许改变了,即便在构造内部也是不允许的。
  静态成员变量并不属于某个类对象,而是整个类共有的。静态成员变量可以不依附于某个实例化后的类对象进行访问。那么,静态成员变量的值,应该在任何实例化操作之前,就能够进行改变(否则,只有实例化至少一个对象,才能访问静态成员)。所以,静态成员变量不能够由构造函数进行内存分配,而应该在类外部单独定义,在实例化任何对象之前,就开辟好空间。又由于 const 成员变量 必须初始化,所以静态成员变量必须在定义的时候就初始化。
  2,const成员函数
  const成员函数指的是,此函数不应该修改任何成员变量。
  1)传给const成员函数的this指针,是指向 const 对象 的 const 指针。
  2)const成员函数,不能够修改任何成员变量,除非成员变量被 mutable 修饰符修饰。
1 class constTestClass
2 {
3 public:
4     int var;
5     const int ci;
6     mutable  int mci;
7 public:
8     void setVar(int i);
9     void setMci(int i)const;
10 };
11 void constTestClass::setVar(int i)
12 {
13     var = i; // ok
14     mci = i; // ok
15     ci = i;  // Error:ci是一个const对象不能修改
16 }
17 void constTestClass::setMci(int i)const
18 {
19     var = i;    // ok
20     mci = i;    // ok  mutable成员变量可以被const成员函数修改
21     ci = i;    // Error
22 }
  在成员函数调用的过程中,都有一个 this 指针被当做参数隐性地传递给成员函数(可能通过栈,也可能通过CPU寄存器)。这个this指针,指向调用这个函数的对象(这样,成员函数才能找到成员变量的地址,从而对其进行操作)。这个this指针,是个 const指针,不能修改其指向(你不希望这个对象的函数,修改了那个对象的成员变量,对吧?)。
  传递给const成员函数的this指针,指向一个const对象。也就是说,在const成员函数内部,这个this指针是一个指向const对象的const指针。
  mutable 修饰符使得const函数的行为有了一些灵活性。相当于提醒编译器,这个成员变量比较特殊,就不要进行任何只读检查了。
  为什么 const 对象只能够调用const成员函数呢?,其实是这样的。由于对象本身通过 const 修饰,那么指向这个对象的指针也就是指向const对象的const指针了。换句话说,指向这个对象的this指针就是指向const对象的const指针。一般成员函数要求的this指针为:指向对象的const指针。所以此处发生了参数不匹配,无法进行调用。而 const 成员函数要求的this指针,恰恰是 指向const对象的const指针。所以依然能够调用。
43/4<1234>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号