C++11:构造函数及类的初始化

C++11:初始化

C++11中成员变量的初始化主要包括三类变量:

  • 普通成员变量
  • 常量
  • 静态变量
  • 静态常量
  1. 普通成员变量的初始化
    有三种初始化的形式:利用{}/=进行本地初始化;初始化列表;先声明,在构造函数体内进行初始化,其中三种方式可以同存,初始化列表后作用于变量。其中,{}初始化的方式可以防止类型的隐形转换。
    例:
#include <iostream>

class wget {
private:
    int exm{0};
    //int exm = 0;

public:
    wget(){
        std::cout<<"Default Constructor"<<std::endl;
    }
    wget(int exm):exm(exm){
        std::cout<<"Constructor"<<std::endl;
    }
    wget(const wget&){
        std::cout<<"Copy Constructor"<<std::endl;
    }
    wget(wget&&){
        std::cout<<"Move Constructor"<<std::endl;
    }
    ~wget(){
        std::cout<<"Destructor"<<std::endl;
    }

    friend std::ostream& operator<<(std::ostream& out,const wget&);
};

std::ostream& operator<<(std::ostream& out,const wget& wg){
    out<<"Exm: "<<wg.exm;
    return out;
}

int main(int argc,char* argv[]){
    wget a = wget(1);
    wget b = wget();
    std::cout<<a<<std::endl;
    std::cout<<b<<std::endl;
    return 0;
}
  1. 常量
    常量可以通过利用{}/=就地初始化,或者使用初始化列表进行初始化。
class wget {
private:
    int exm{0};
    //const double price{0};
    const double price;
    //int exm = 0;

public:
    
    wget(int a=0):price(a){
        std::cout<<"Default Constructor"<<std::endl;
    }
    /*
    wget(){
        std::cout<<"Default Constructor"<<std::endl;
    }
    wget(int exm):exm(exm){
        std::cout<<"Constructor"<<std::endl;
    }
    */
    wget(const wget& rhs):price(rhs.price){
        exm = rhs.exm;
        std::cout<<"Copy Constructor"<<std::endl;
    }
    wget(wget&& rhs):price(rhs.price){
        exm = rhs.exm;
        std::cout<<"Move Constructor"<<std::endl;
    }
    ~wget(){
        std::cout<<"Destructor"<<std::endl;
    }

    friend std::ostream& operator<<(std::ostream& out,const wget&);
};

std::ostream& operator<<(std::ostream& out,const wget& wg){
    out<<"Exm: "<<wg.exm<<"\n";
    out<<"Const Var: "<<wg.price;
    return out;
}
  1. 静态变量
    静态变量由于不属于任何一个类实例,因此,静态变量需要在类外进行初始化,并且不应该在声明文件中;
class wget {
private:
    int exm{0};
    const double price{0};
    //const double price;
    //int exm = 0;
    static int var;

public:
    
    wget(int a=0):price(a){
        std::cout<<"Constructor"<<std::endl;
    }
    wget(const wget& rhs):price(rhs.price){
        exm = rhs.exm;
        std::cout<<"Copy Constructor"<<std::endl;
    }
    wget(wget&& rhs):price(rhs.price){
        exm = rhs.exm;
        std::cout<<"Move Constructor"<<std::endl;
    }
    ~wget(){
        std::cout<<"Destructor"<<std::endl;
    }

    friend std::ostream& operator<<(std::ostream& out,const wget&);
};

int wget::var = 2;

std::ostream& operator<<(std::ostream& out,const wget& wg){
    out<<"Exm: "<<wg.exm<<"\n";
    out<<"Const Var: "<<wg.price<<"\n";
    out<<"Static Var: "<<wget::var;
    return out;
}
  1. 静态常量
    静态常量可以在声明时初始化{}/=,以及在类外进行初始化。
class wget {
private:
    int exm{0};
    const double price{0};
    //const double price;
    //int exm = 0;
    const static int var{2};

public:
    
    wget(int a=0):price(a){
        std::cout<<"Constructor"<<std::endl;
    }
    wget(const wget& rhs):price(rhs.price){
        exm = rhs.exm;
        std::cout<<"Copy Constructor"<<std::endl;
    }
    wget(wget&& rhs):price(rhs.price){
        exm = rhs.exm;
        std::cout<<"Move Constructor"<<std::endl;
    }
    ~wget(){
        std::cout<<"Destructor"<<std::endl;
    }

    friend std::ostream& operator<<(std::ostream& out,const wget&);
};

//const int wget::var = 2;

std::ostream& operator<<(std::ostream& out,const wget& wg){
    out<<"Exm: "<<wg.exm<<"\n";
    out<<"Const Var: "<<wg.price<<"\n";
    out<<"Static Var: "<<wget::var;
    return out;
}
  1. 引用成员
    通过使用初始化列表进行初始化,或利用{}/=就地初始化。
class wget {
private:
    int exm{0};
    const double price{0};
    //const double price;
    //int exm = 0;
    const static int var{2};
    int& ref;

public:
    
    wget(int& a):ref(a){
        std::cout<<"Constructor"<<std::endl;
    }
    wget(const wget& rhs):price(rhs.price),ref(rhs.ref){
        exm = rhs.exm;
        std::cout<<"Copy Constructor"<<std::endl;
    }
    wget(wget&& rhs):price(rhs.price),ref(rhs.ref){
        exm = rhs.exm;
        std::cout<<"Move Constructor"<<std::endl;
    }
    ~wget(){
        std::cout<<"Destructor"<<std::endl;
    }

    friend std::ostream& operator<<(std::ostream& out,const wget&);
};

编译器默认生成的函数

C++11中存会自动生成以下几类特殊函数:

  • 默认构造函数
  • 拷贝构造函数
  • 拷贝赋值函数
  • 移动构造函数
  • 移动赋值函数
  • 析构函数
    其中,对于默认构造函数,只有没有声明任何一个构造函数时,编译器才会在需要的时候自动生成。
    对于拷贝函数(构造和赋值)遵从C++98的语法标准,相互独立,声明了其中一个,编译器在需要的时候仍会自动生成另一个。但是若果声明了移动操作,则拷贝操作会被置为=deleted。
    对于移动构造及移动赋值,若未声明拷贝操作、移动操作、析构函数,则会自动生成。
    析构函数的自动生成遵从98语法。只是在C++11中,声明为noexcept。
    默认规则:声明了拷贝或移动操作,则应该声明所有的拷贝、移动、析构操作。

继承体系中的初始化方式

虚继承

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容