转:常量函数、常量引用参数、常量引用再次来到值

1. 有关常量引用
正像在C语言中应用指针1样,C++中常见选择引用 
有贰个函数
… foo()
还要这一个函数重返三个引用…
… & foo()
…., 一个针对性位图(Bitmap)的引用 …
Bitmap & foo()
…. 并且那些位图(bitmap)是常量
const Bitmap & foo ()

当然你也得以用指针来做壹样的事务:
const Bitmap * foo()
foo 重返3个指南针 … 指向一个Bitmap … 并有那个Bitmap是个常量.
Bitmap * const foo()
foo 再次回到有些东西,那么些事物是常量 … 那些事物又是指针 … 三个指向Bitmap的指针.
const Bitmap * const foo()
foo 重回某些东西,那几个事物是常量 … 这一个事物又是指针 … 1个指向Bitmap的指针.
….
再者这么些Bitmap也是常量.

const总是针对它右边的东西起效果, 唯1不一致的是,借使const是贰个最左侧的标识符,那么const将对准它右侧的东西起效果,因些 const int i; 与 int const i; 意思是同一的.

 

二. 常量函数、常量引用参数、常量引用再次回到值
例1:bool verifyObjectCorrectness(const myObj &obj); //const reference parameter
例2:void Add(const int &arg) const; //const function
例3:IStack const & GetStack() const { return _stack; } //return const reference

常量引用参数
本例中,1个myObj类型的指标obj通过引用传入函数verifyObjectCorrectness。为安全起见,使用了const关键字来担保函数verifyObjectCorrectness不会变动指标obj所引用的目的的气象。其余,通过注解参数常量,函数的使用者能够有限协助他们的对象不会被改动,也不必顾虑在调用函数时带来副成效。以下代码试图对注脚为常量引用的形参实行改动,从而不会透过编写翻译!

 #include  < iostream > 
 using namespace std;

 class  Test
{
    public :
     void  f( const   int &  arg);
    private :
     int  value; 
} ;

 void  Test::f( const   int &  arg)  
 {
    arg= 10;  // 试图修改arg的值,此行将引起编译器错误 // error C2166: l-value specifies const object 
    cout << " arg= " << arg << endl; 
    value = 20 ;
}   

 void  main()
 {
   int  i = 7 ;
  Test test;
  test.f(i);
  cout << " i= " << i << endl; 
} 

 

三、常量函数 
1). 三个函数通过在其后边加关键字const,它将被声称为常量函数
2). 在C++,只有将成员函数申明为常量函数才有含义。带有const作后缀的常量成员函数又被叫作视察者(inspector),没
    有const作后缀的相当量成员函数被称呼变异者(mutator)
叁). 与const有关的错误总是在编译时意识
4). [摘]If the function is not declared const, in can not be applied to a const object, and the compiler will  
         give an error message. A const function can be applied to a non-const object 
5). 在C++中,3个目的的有着办法都收到叁个针对对象自笔者的盈盈的this指针;常量方法则收获了贰个分包的常量this指针
    void func_name() const;
    以上表达函数func_name()不会改变*this。当您把this指针看成函数func_name()的一个不可知参数就精晓了
    void func_name(T *this) (no const)
    void func_name(const T *this) (const)
6). 常量函数能够被其余对象调用,而格外量函数则只可以被十分量对象调用,无法被常量对象调用,如:

  class  Fred   
{
  public :
     void  inspect()  const ;    //  This member promises NOT to change *this 
     void  mutate();           //  This member function might change *this 
  } ;

  void  userCode(Fred &  changeable,  const  Fred &  unchangeable)
   {
    changeable.inspect();    //  OK: doesn't change a changeable object 
    changeable.mutate();     //  OK: changes a changeable object 

    unchangeable.inspect();  //  OK: doesn't change an unchangeable object 
    unchangeable.mutate();   //  ERROR: attempt to change unchangeable object 
  }  

 #include  < iostream > 
 using namespace std;

struct A
  {
     void  f()  const   { cout << " const function f is called " << endl; } 
      void  f()   { cout << " non-const function f is called " << endl; } 
      void  g()   { cout << " non-const function g is called " << endl; }  
} ;

 void  main()
  {
     A a;
     const  A &  ref_a  =  a;
     a.f();  // calls void f() 
     ref_a.f(); // calls void f () const 
     a.g();  // ok, normal call 
     ref_a.g();  // error, const object can not call non-const function 
 }

 

 7). 在类中允许存在同名的常量函数和丰盛量函数,编写翻译器根据调用该函数的目的选拔合适的函数
    当卓殊量对象调用该函数时,先调用卓殊量函数;
    当常量对象调用该函数时,只可以调用常量函数;
    假如在类中唯有常量函数而未有与其同名的尤其量函数,则万分量与常量对象都可调用该常量函数;如:

#include  < iostream > 
 using namespace std;

struct A
  {
      void  f()  const    { cout << " const function f is called " << endl; } 
      void  f()   { cout << " non-const function f is called " << endl; } 
  } ;

 void  main()
  {
     A a;
     const  A &  ref_a  =  a;
     a.f(); //calls void f()
     ref_a.f(); // calls void f () const 
 }

 

    图片 1 

出口结果:
non-const function f is called
const function f is called图片 2 

 

#include  < iostream > 
 using namespace std;

struct A  
{
     void  f()  const    { cout << " const function f is called " << endl; } 
} ;

 void  main()
  {
     A a;
     const  A &  ref_a  =  a;
     a.f();  // calls void f() const 
     ref_a.f(); // calls void f () const 
 }

 

 输出结果:
const function f is called
const function f is called

八). 以下代码试图修改类的数额成员,引起编写翻译错误图片 3 

#include  < iostream > 
 using namespace std;

 class  Test
  {
    public :
       void  f( const   int &  arg)  const ;
    private :
       int  value; 
} ;

 void  Test::f( const   int &  arg)  const
  {
     // arg=10;  
     cout << " arg= " << arg << endl; 
     value = 20 ;  // 试图修改Test的数据成员,此行将引起编译器错误  // error C2166: l-value  specifies const object 
 }   

 void  main()
  {
   int  i = 7 ;
  Test test;
  test.f(i);
  cout << " i= " << i << endl; 
} 

 

9). const关键字无法用在构造函数与析构函数中。因为构造函数的指标是起首化域值,因而它必须变更对象,析构函数同理

四、常量引用重返值
若果您想从常量方法(函数)中经过引用重临this对象的一个成员, 你应该采用常量引用来回到它,即const X&
也便是说你想透过引用再次回到的事物若是从逻辑上来讲是this对象的一有的(与它是或不是在物理上停放在this对象中非亲非故),那么常量方法需求经过常量引用可能通过值来回到,而无法经过卓殊量引用返回
初稿请参见:http://www.parashift.com/c++-faq-lite/const-correctness.html\#faq-18.10

class Person
 {
   public:
      const string& name_good() const; // Right: the caller can't change the name
      string& name_evil() const;       // Wrong: the caller can change the name
    .
};

void myCode(const Person& p) // You're promising not to change the Person object
{
    p.name_evil() = "Igor";  // but you changed it anyway!!

}