zoukankan      html  css  js  c++  java
  • C++总的const使用说明

    C++总的const使用说明

    1. const修饰类成员变量

      程序:

    #include <iostream>
    using namespace std;
    
    class A
    {
        public:
            A(int size) : SIZE(size) {};
        private:
            const int SIZE;
    };
    
    int main()
    {
        A a(100);
    }

      说明:
      (1)    在类中声明变量为const类型,但是不可以初始化;

      (2)    const常量类的成员变量的初始化必须在构造函数初始化列表中初始化,而不可以在构造函数函数体内初始化。

      (3)  如果其作为C类的成员定义,因为不可以在C类定义创建对象,则可以采用如下措施:

             使用指针,然后在C类的构造函数中,用new 在堆空间创建对象,然后天数const的成员初始化。

      

       此时的const变量属于具体的一个对象,如何在整个类中都恒定不变呢

       答案是利用枚举

    #include <iostream>
    using namespace std;
    
    class A
    {
        private:
            enum {SIZE = 100};
        public:
            int array[SIZE];
    };
    
    int main()
    {
        A a;
    }

      问题说明:

      (1)枚举常量不会占据对象的存储空间,在编译时被全部求值

      (2)但是,它隐含的数据对象类型为整形,不能表示其他类型

    2. 必须在构造函数的初始化列表中初始化的情况

      (1)类的const常量;

      (2)类的引用类型成员;

    #include <iostream>
    using namespace std;
    
    class A
    {
        public:
            A(int &v) : i(v), p(v), j(v) {}
            void print_val() { cout << "hello:" << i << "  " << j << endl;}
        private:
            const int i;
            int p;
            int &j;
    };
    
    int main(int argc ,char **argv)
    {
        int pp = 45;
        A b(pp);
        b.print_val();
    }

       究其因

      ① const对象引用只能列表初始化但是不能赋值

      ②  构造函数的函数体内只能做赋值而不是初始化,因此初始化const对象或引用的唯一机会是构造函数函数体之前初始化列表中

      ③ 明白两个概念:

      从无到有叫初始化,初始化(调用拷贝构造函数创建了新对象

      赋值(调用赋值操作符没有创建新对象,而是对已有的对象赋值。

      (3)没有默认构造函数的类类型成员

    #include <iostream>
    using namespace std;
    
    class Base
    {
        public:
            Base(int a) : val(a) {}
        private:
            int val;
    };
    
    class A
    {
        public:
            A(int v) : p(v), b(v) {}
            void print_val() { cout << "hello:" << p << endl;}
        private:
            int p;
            Base b;
    };
    
    int main(int argc ,char **argv)
    {
        int pp = 45;
        A b(pp);
        b.print_val();
    }

       原因同样是创建对象时,要初始类成员的每一个成员

      (4)如果类存在继承关系,派生类必须在其初始化列表中调用基类的构造函数

    #include <iostream>
    using namespace std;
    
    class Base
    {
        public:
            Base(int a) : val(a) {}
        private:
            int val;
    };
    
    class A : public Base
    {
        public:
            A(int v) : p(v), Base(v) {}
            void print_val() { cout << "hello:" << p << endl;}
        private:
            int p;
    };
    
    int main(int argc ,char **argv)
    {
        int pp = 45;
        A b(pp);
        b.print_val();
    }

    3. const成员函数与非const 成员 函数问题

      (1) 任何不修改数据成员的函数都应该声明为const类型

      如果在编写const成员函数时,①不慎修改了数据成员,②或调用了其他非const成员函数,编译器就会指出错误。应该养成一个好的习惯。

      注意:在const修饰类的成员数据时,一般在const声明在函数声明的后边;

    #include <iostream>
    using namespace std;
    class Stack
    {
        public:
            void Push(int item);
            int Pop(void);
            int GetCount(void) const;//const 后置
        private:
            int m_num; 
            int m_data[100];
    };
    
    int Stack::GetCount(void) const
    {
        ++m_num;     //编译错误,企图修改数据成员
        Pop();       //编译错误,企图调用非const函数
        return m_num;
    }

      (2)同一个类中,可以仅通过是否是const定义两个函数名字、参数、返回值完全相同的两个成员函数,依据类对象是否为const对象分别调用。

      程序:

    #include <iostream>
    using namespace std;
    
    class A
    {
        public:
            A(int v): val(v) {}
            void print_val() { cout << "not const:" << val << endl;}
            void print_val() const { cout << "const print_val:" << val << endl;}
        private:
            int val;
    };
    int main(int argc ,char **argv)
    {
        A b(45);
        b.print_val();
    
        const A a(12);
        a.print_val();
    }

      输出:

      

      总结:

      同函数名、参数、返回值可以仅通过是否为const来定义为类的两个成员函数。

      在调用时,const对象调用const成员函数,非const对象调用非const成员函数。

    (3)非const的成员函数,可以调用const的成员函数,

      当一个只有const成员函数的时候,非const对象也可以调用const成员函数

    class A  
    {  
    public:  
           A( void )  
           {  
           }  
             
           void func( void ) const  
           {  
               cout << "const version" << endl;  
           }  
    };  
      
    int _tmain(int argc, _TCHAR* argv[])  
    {  
        //非const对象调用const成员函数   
      
        A obj;  
        obj.func( );  
          
        //const对象调用const成员函数   
        const A obj_const;  
        obj_const.func( );  
          
        system( "PAUSE" );  
        return EXIT_SUCCESS;  
        return 0;  
    }  

    (4)const对象是不可以调用类中的非const成员函数

     我们知道c++在类的成员函数中还会隐式传入一个指向当前对象的this指针,所以在test类中,实际的print函数应该是这样的void print(test * this);,这代表一个指向test对象的指针this被传入到了print函数中

    假如现在我们用test类创建一个对象,

     test obj1(12);
     obj1.print();

      第二句,obj1.print();其实相当于print(&obj1);,即把当前的对象obj1的指针传递到print()函数,这是没问题的

      如果用test类创建一个const对象,然后去调用print()函数呢?这就会出现问题

    const test obj2(122);
    obj2.print();

      这时obj2对象的指针就会传递给test *this 指针,而obj2的地址翻译成指针类型应该是这样的,const test* this,即这时会出现类型不匹配的错误,在visual studio 中会出现类似于下面的错误:

      所以通过上面的说明,我们知道了为什么const 对象不能调用非const成员函数。

    4. const的一些问题

      (1)不可以在const函数中改变成员变量的值,那么有没有办法改变?

      答案是可以的,把成员变量声明为mutable类型。看程序

    #include <iostream>
    using namespace std;
    
    class A
    {
        public:
            A(int v): val(v) {}
            void print_val() { cout << "not const:" << val << endl;}
            void print_val() const { val++; cout << "const print_val:" << val << endl;}
        private:
            mutable int val;
    };
    int main(int argc ,char **argv)
    {
        A b(45);
        b.print_val();
    
        const A a(12);
        a.print_val();
    }

      输出:

      

      说明:

      mutalbe的中文意思是“可变的,易变的”,跟constant(既C++中的const)是反义词。

      在C++中,mutable也是为了突破const的限制而设置的。被mutable修饰的变量,将永远处于可变的状态,即使在一个const函数中。

      我们知道,如果类的成员函数不会改变对象的状态,那么这个成员函数一般会声明成const的。但是,有些时候,我们需要在const的函数里面修改一些跟类状态无关的数据成员,那么这个数据成员就应该被mutalbe来修饰

      (2)当类中只有const函数,非const对象是否可以调用const函数?

      答案是可以的,范围并没有被扩大。

      但是:只有const函数时,非const对象不可以调研那个const函数(否则,类的数据变量就会发生变化)。

      (3)当类中存在只有 是否为const 不同的两个函数时,const函数是否可以暂时调用那个非const函数?

       答案是可以的。用const_cast将转化掉表达式的const性质

    #include <iostream>
    using namespace std;
    
    class A
    {
        public:
            A(int v): val(v) {}
            void print_val() { cout << "not const:" << val << endl;}
            void const print_val() const { cout << "const print_val:" << val << endl;}
        private:
            int val;
    };
    int main(int argc ,char **argv)
    {
        A b(45);
        b.print_val();  //非const
    
        const A *a = new A(45);
        const_cast<A*>(a)->print_val();  //()调用非const的重载函数
        a->print_val();  //调用const的从在函数
    }

      输出:

      

      注意;const_cast<A*> (a)只对本地转化有效,且必须使用类的指针进行处理。

      单纯用类转化不行,直接用类的对象不行。

    const A a(45);
    const_cast<A> a.print_val();

      编译不通过,错误

      (4)返回类型是const是怎么回事?

      const返回类型只有在修饰指针或引用是才有用。单凭const返回类型不可以重载。

     

      参考网址:

            http://www.cnblogs.com/kaituorensheng/p/3244910.html

  • 相关阅读:
    Java Web 网络留言板2 JDBC数据源 (连接池技术)
    Java Web 网络留言板3 CommonsDbUtils
    Java Web ConnectionPool (连接池技术)
    Java Web 网络留言板
    Java Web JDBC数据源
    Java Web CommonsUtils (数据库连接方法)
    Servlet 起源
    Hibernate EntityManager
    Hibernate Annotation (Hibernate 注解)
    wpf控件设计时支持(1)
  • 原文地址:https://www.cnblogs.com/icmzn/p/5059428.html
Copyright © 2011-2022 走看看