zoukankan      html  css  js  c++  java
  • C++类中const, static, reference等类型成员的初始化

    有些成员变量的数据类型比较特别,它们的初始化方式也和普通数据类型的成员变量有所不同。这些特殊的类型的成员变量包括:

    a. 常量型成员变量(const)

    b. 引用型成员变量 (&)

    c. 静态成员变量 (static)

    d. 整型静态常量成员变量 static const int

    e. 非整型静态常量成员变量 static const double

    1. 常量型成员初始化:只能在构造函数的初始化列表中进行直接初始化。

    如:

    class Test {
    public:
    const int MY_MASK;
    Test() : MY_MASK(0xff) {}
    };

    如果不是在初始化列表中对 const 常量进行初始化,而是在构造函数中对其赋值的话,是不能成功的。很简单的道理:不能给 const 成员赋值。 同样的道理,如果要初始化一个引用类型的成员变量,也不能在构造函数体内赋值,而只能在构造函数的初始化列表中进行初始化。

     

    2. 引用型变量的初始化:也必须在构造函数的初始化列表中。

    而所有的运算符操作都被视为赋值而不是初始化,所以引用参数的初始化必须在初始化列表中进行。

    class Test{
    public:
    Test(int val) : ref_(val){}
    ~Test() {}
    private:
    int & ref_;};
    int main(){
    Test t(1);
    int a=1;
    Test t2(a);
    return 0;
    }

    3. 静态成员的初始化:

    类中的static变量是属于类的,不属于某个对象,它在整个程序的运行过程中只有一个副本,因此不能在定义对象时 对变量进行初始化,就是不能用构造函数进行初始化,其正确的初始化方法是:

    数据类型 类名::静态数据成员名=值;

    class Test{
    public:
    static int MASK;//声明int 型的MASK 常量
    };
    int Test::MASK=0xFFFF;//定义

    这表明:

    (1)、初始化在类体外进行,而前面不加static,以免与一般静态变量或对象相混淆

    (2)、初始化时不加该成员的访问权限控制符private、public等

    (3)、初始化时使用作用域运算符来表明它所属的类,因此,静态数据成员是类的成员而不是对象的成员。

    4. 静态常量成员初始化

    初始化 static const 成员,也就是全局的静态常量,和常量成员的初始化化类似,在类内声明,在类外定义。比如:

    class Test{
    public:
    static const int MASK;// 申明int 型的MASK 常量,
    };
    const int Test::MASK = 0xFFFF;// 定义Test::MASK 常量,注意这里不需要static 关键字

    但是对于整型静态常量成员与非整型的还是有差别的,这个其实是和编译器相关的。

    比如:

    class Test{
    public:
        static const int i1=3;
        const static int i2=4;
        static const double a1=3.3;
        const static double a2=5.7;
    };

    使用gcc编译器时,上面的写法是没问题的。但是在VS2008下进行编译的报错:

    改成下面的方式就问题了:

    class Test{
    public:
        static const int i1=3;
        const static int i2=4;
        static const double a1;
        const static double a2;
    };
    const double Test::a1=3.3;
    const double Test::a2=5.7;

    注意:在const成员函数中,可以修改static成员变量的值。普通成员变量的值,是不能修改的。

    一个完整的例子如下(带有注释):

    #include <iostream>
    using namespace std;
    class BClass {
        public:
        BClass() : i(1), ci(2), ri(i) // 对于常量型成员变量和引用型成员变量,必须通过参数化列表的方式进行初始化。在构造函数体内进行赋值的方式,是行不通的。
        { }  

        void print_values() {
            cout << "i =\t" << i << endl;
            cout << "ci =\t" << ci << endl;
            cout << "ri =\t" << ri << endl;
            cout << "si =\t" << si << endl;
            cout << "csi =\t" << csi << endl;
            cout << "csi2 =\t" << csi2 << endl;
            cout << "csd =\t" << csd << endl;
        }
        private:
        int i; // 普通成员变量
        const int ci; // 常量成员变量
        int &ri; // 引用成员变量
        static int si; // 静态成员变量
        
    //static int si2 = 100; // error: 只有静态常量成员变量,才可以这样初始化
        static const int csi; // 静态常量成员变量
        static const int csi2 = 100// 静态常量成员变量的初始化(Integral type) (1)
        static const double csd; // 静态常量成员变量(non-Integral type)
        
    //static const double csd2 = 99.9; // error: 只有静态常量整型数据成员才可以在类中初始化(和编译器相关)

    };
    // 静态成员变量的初始化(Integral type)
    int BClass::si = 0;
    // 静态常量成员变量的初始化(Integral type)
    const int BClass::csi = 1;
    // 静态常量成员变量的初始化(non-Integral type)
    const double BClass::csd = 99.9;
    // 在初始化(1)中的csi2时,根据Stanley B. Lippman的说法下面这行是必须的。
    // 但在VC2003中如果有下面一行将会产生错误,而在VC2005/gcc中,下面这行则可有可无,这个和编译器有关。
    const int BClass::csi2;

    int main(void)
    {
        BClass b_class;
        b_class.print_values();
        return 0;
    }
  • 相关阅读:
    mybatis中的延迟加载
    MyBatis的mapper
    MyBatis的resultMap
    mybatis入门
    mybatis中的#和$的区别(转)
    操作日志记录
    SpringMVC中的异常处理集锦
    vue.js的package.json相关问题解惑
    git的常用操作指令
    http协议参数详解
  • 原文地址:https://www.cnblogs.com/xkfz007/p/2655847.html
Copyright © 2011-2022 走看看