zoukankan      html  css  js  c++  java
  • 转:常量函数、常量引用参数、常量引用返回值

    1. 关于常量引用
    正像在C语言中使用指针一样,C++中通常使用引用 
    有一个函数
    ... foo()
    并且这个函数返回一个引用...
    ... & foo()
    ...., 一个指向位图(Bitmap)的引用 ...
    Bitmap & foo()
    .... 并且这个位图(bitmap)是常量
    const Bitmap & foo ()

    当然你也可以用指针来做同样的事情:
    const Bitmap * foo()
    foo 返回一个指针 ... 指向一个Bitmap ... 并有这个Bitmap是个常量.
    Bitmap * const foo()
    foo 返回某个东西,这个东西是常量 ... 这个东西又是指针 ... 一个指向Bitmap的指针.
    const Bitmap * const foo()
    foo 返回某个东西,这个东西是常量 ... 这个东西又是指针 ... 一个指向Bitmap的指针.
    ....
    并且这个Bitmap也是常量.

    const总是针对它左边的东西起作用, 唯一例外的是,如果const是一个最左边的标识符,那么const将针对它右边的东西起作用,因些 const int i; 与 int const i; 意思是相同的.

    2. 常量函数、常量引用参数、常量引用返回值
    例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

    常量引用参数
    本例中,一个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; 
    } 
    

    3、常量函数 
    1). 一个函数通过在其后面加关键字const,它将被声明为常量函数
    2). 在C++,只有将成员函数声明为常量函数才有意义。带有const作后缀的常量成员函数又被称为视察者(inspector),没
        有const作后缀的非常量成员函数被称为变异者(mutator)
    3). 与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++中,一个对象的所有方法都接收一个指向对象本身的隐含的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 
     }
    

        常量函数、常量引用参数、常量引用返回值[C++] - 风殇 - 张霁的博客 

    输出结果:
    non-const function f is called
    const function f is called常量函数、常量引用参数、常量引用返回值[C++] - 风殇 - 张霁的博客 

    #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


    8). 以下代码试图修改类的数据成员,引起编译错误常量函数、常量引用参数、常量引用返回值[C++] - 风殇 - 张霁的博客 

    #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关键字不能用在构造函数与析构函数中。因为构造函数的目的是初始化域值,因此它必须更改对象,析构函数同理

    4、常量引用返回值
    如果你想从常量方法(函数)中通过引用返回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!!
    
    }
    
  • 相关阅读:
    firefox 插件开发2
    android ndk
    android Fragment.
    排序算法
    php中判断iphone版本
    php css
    ndk 入门实例
    howtoaddabuttontopreferencescreen 自定义view
    分布式K/V存储方案
    android版 eclipse
  • 原文地址:https://www.cnblogs.com/ATually/p/2440632.html
Copyright © 2011-2022 走看看