构造函数@C++

基本概念

构造函数 类中的特殊函数 用于描述初始化算法

作用

在对象被创建时使用特定值构造对象

将对象初始化为一个特定状态

  如 在构造一个clock类的时候

  把初始时间设为0 0 0就可以通过构造函数来设置

形式

  函数名与类名相同

  不能定义返回值类型,不能有return

  可以有形式参数,也可以没有形式参数

  可以是内联函数

  可以重载

  可以带默认值

调用时机

  对象被创建时自动被调用

  如

  创建对象的时候给初始值 构造函数自动被调用 Clock myClock (0,0,0);

  如果没有这样形式的构造函数 那么编译器报错 说不存在这样形式的构造函数

默认构造函数

  调用时不需要实参的构造函数

    参数表为空

    全部参数为默认值

      两个默认构造函数不能同时出现在一个类中

建立新对象 一定会调用构造函数

  如果定义类时不声明一个构造函数 那么编译器在编译时会自动生成一个构造函数(隐含默认构造函数)

    隐含生成默认构造函数

      参数列表为空

      类内定义成员初始值,使用该值

      没有定义,则默认方式初始化,默认方式初始化的值不确定

=default

程序已经定义构造函数 那么编译器不再隐含生成默认函数,如果此时希望编译器隐含生成默认函数,则使用=default

  

class Clock {
public:
    Clock() = default;//指示编译器提供默认构造函数private:
    int hour, minute, second;
};

以下是之前例子的带构造函数扩展

#include<iostream>
using namespace std;

class Clock {
public:
    Clock(int newH, int newM, int newS);//构造函数   不能定义返回值类型 void也不行
    Clock();//构造函数重载 默认构造函数
    void setTime(int newH, int newM, int newS);
    void showTime();
private:
    int hour, minute, second;
};

Clock::Clock(int newH, int newM, int newS) ://类名写前面 无返回值类型 构造函数也是成员函数 成员函数实现的时候都要写类名
    hour(newH), minute(newM), second(newS)//初始化列表 还记得c++中给变量赋初值的另一种方法吗 如 int a(3) 这里采用同样的方法,意思是 将函数收到的newH赋值给类中的hour 
{}//当然上面的初始化列表可以写到函数体中,但是并不方便

Clock::Clock() :hour(0), minute(0), second(0){}//默认构造函数 给hour赋值0,以此类推

void Clock::setTime(int newH, int newM, int newS)
{
    hour = newH;
    minute = newM;
    second = newS;
}

void Clock::showTime()
{
    cout << hour << ":" << minute << ":" << second<<endl;
}

int main() {
    Clock c;//调用构造函数 此处不给初始值,因此调用默认构造函数
    Clock c2(1,2,3);//不管有没有参数,调用创建对象的时候都会调用构造函数,如果类中没有定义构造函数,那么编译器会隐含生成一个构造函数,但如果你定义了,且没有再定义默认构造函数->
    c.showTime();//那么当你创建一个新对象但不给初值的时候会报错
    cout << ".....................\n";
    c2.showTime();
    cout << ".....................";
    cout <<endl<< "已初始化" << endl;
    int h, m, s;
    cout << "请设定时分秒" << endl;
    cin >> h >> m >> s;
    c.setTime(h, m, s);
    c.showTime();
    cout <<endl<< "时间已设定" << endl;
    return 0;
}

委托构造函数

上面的两个构造函数功能几乎一样可以采用委托构造函数来简化,最重要的是,委托构造函数可以保证两个构造函数的一致性,以后修改一次,那么委托他的那些构造函数也会被修改

Date(int year,int month,int day):_year(year), _month(month), _day(day){}//其声明在class内,但 :  以后的内容可以在class外定义,不影响后面构造函数的委托

//其余构造函数全都委托给第一个构造函数

Date() :Date(1990,1,1){}

Date(int year) :Date(){}

复制构造函数

用已经存在的对象去初始化新对象  类似于

int a=0;
int b=a;

以上操作是c++定义好的,所以可以直接用,但类中并没有定义这种操作,因此需要去定义

 

隐含的复制构造函数

,如果没有自定义复制构造函数,编译器会为我们生成一个默认的复制构造函数 该函数会实现两个对象数据成员的一一对应复制 

很多时候,该默认函数就能令人满意了,因此这样的话就不需要自己写复制构造函数,但是另一些时候,我们需要自己规定复制构造函数 比如说 对象里面有指针,编译器给的默认复制构造函数就不够用了,或者有特殊的复制需求

 

复制构造函数的定义

 该函数的形参是本类对象的引用,作用是用已存在的对象去初始化同类型的新对象

格式是

class内声明        类名 (const 类名 &对象名);  //&引用符号 如果该函数对形参做了任何修改,那么对实参也会做相同的修改 为保证安全性 需要限定符const

class外实现   类名::类名 (const 类名 &对象名)//前面的类名表示该函数所在类的名字,后面的类名是因为它是构造函数,因此函数名就是类名

        {函数体}

 

调用复制构造函数的3种情况

  1.定义对象时用本类的另一个对象去初始化

  2.函数的形参是类的对象(而不是类的对象的引用),在此过程中会发生对象的值的传递 此时要调用复制构造函数

  3.函数的返回值是类的对象 函数执行结束 返回主调函数 的时候   使用return语句中的对象初始化一个无名对象再传递给主调函数 发生复制构造   

          这种情况可以通过移动构造避免不必要的复制

 

=delete

不希望对象被复制构造时,用=delete指示编译器不生成默认复制构造函数

在point类中声明

point(const point& p) = delete;

posted on 2018-03-02 13:14  晴未  阅读(141)  评论(0编辑  收藏  举报