类与对象\构造函数与析构函数

简介: 类与对象\构造函数与析构函数

一、构造函数

  • 特殊的成员函数
  • 定义类的对象时,系统自动调用构造函数来创建并初始化对象
  • 与普通函数定义方式相同
  • 实现:类内√        类外√

特点

  • 函数名必须与类名相同
  • 无返回值类型
  • public属性
  • 只在创建对象时由系统自动调用

代码实例

#include <iostream>
using namespace std;
 
class CDate
{
private:
    int Date_Year, Date_Month, Date_Day;
public:
    CDate(int, int, int);
    void Display();
};
 
//在类外定义构造函数
CDate::CDate(int year, int month, int day)
{
    cout << "Constructor called" << endl;
    Date_Year = year;
    Date_Month = month;
    Date_Day = day;
}
 
//在类外定义Display()函数
void CDate::Display()
{
    cout << "Date: " << Date_Day << "/" << Date_Month << "/" << Date_Year << endl;
}
 
 
int main() 
{
    CDate today(2024,3,17);
    cout << "---------------------" << endl;
    today.Display();
    return 0;
}

系统默认的构造函数

  • 类定义中没有定义构造函数,编译器自动生成默认的构造函数
  • 无形参
  • 无语句
  • 仅用于创建对象,为对象分配空间
  • 不初始化其中成员数据
  • 如果类定义中已经为类提供了任意一种形式的构造函数,编译器不再提供默认无参构造函数
  • 需要用户自己定义
  • 一个类可以拥有多个构造函数(可重载)

具有默认参数值的构造函数

在定义构造函数时,为避免出现因参数数量不同而找不到合适的构造函数,建议构造函数采用带默认参数值的形式比较安全

初始化列表

  • 初始化列表是初始化对象某些特殊数据成员的唯一方法
  • 引用&const
  • 注意
  • 系统调用构造函数时,先执行初始化列表
  • 成员间可以相互初始化
  • 成员初始化的顺序只与声明顺序有关,与初始化顺序无关

代码实例

#include <iostream>
using namespace std;
 
class Circle
{
private:
    int radius;
    int &b=radius;
    const double pi=3.14;
public:
    Circle(int r):radius(r)
    {
        radius=r;
        cout<<radius<<" "<<b<<" "<<pi<<endl;
    }
    void show()
    {
        cout<<"area="<<pi*radius*radius<<endl;
    }
};
 
int main() 
{
    int aa=2;
    Circle c(aa);
    c.show();
    return 0;
}

注:在vs2010中,这段代码是会报错的;但在vscode(使用最新的的mingw)和vs2022(最新版)中都不会报错,且能正常运行

稍作修改

public:
    Circle(int r):radius(r),b(r),pi(3.14)
    {
        radius=r;
        cout<<radius<<" "<<b<<" "<<pi<<endl;
    }

就能正常运行。在老版本中,引用和const只能使用初始化列表来初始化

复制构造函数

  • 同类对象的常引用
  • 不定义复制构造函数,编译器会自动生成
  • 系统自动调用的情况
  • 新对象:由一个已定义的对象初始化一个新对象
  • 传参:函数调用、对象作为实参传递给函数形参时
  • 引用和指针不会调用
  • 返回值:对象作为函数返回值
#include <iostream>
using namespace std;
 
class CDate
{
private:
    int Date_Year, Date_Month, Date_Day;
public:
    CDate(int y=2019, int m=1, int d=1);
    CDate(const CDate& date);
    void Display();
};
 
CDate::CDate(int y, int m, int d): Date_Year(y), Date_Month(m), Date_Day(d)
{
    cout << "Constructor called" << endl;
}
 
CDate::CDate(const CDate& date)
{
    cout << "Copy constructor called" << endl;
    Date_Year = date.Date_Year;
    Date_Month = date.Date_Month;
    Date_Day = date.Date_Day+1;
}
 
void CDate::Display()
{
    cout << Date_Year << "-" << Date_Month << "-" << Date_Day << endl;
}
 
CDate fun(CDate date)
{
    CDate new_date(date);
    return new_date;
}
 
int main() 
{
    CDate date1(2020, 1, 1);    //Constructor called
    cout<<endl;     //换行
    
    CDate date3 ;           //Constructor called
    cout<<endl;     //换行
    
    CDate date2(date1);     //copy_1    //Copy constructor called
    cout<<endl;     //换行
    
    CDate date4 = date1;   //copy_2    //Copy constructor called
    cout<<endl;     //换行
 
    date3 = date2;  //没有输出
    cout<<endl;     //换行
 
    date3 = fun(date2);     //3次Copy constructor called
    cout<<endl;     //换行
 
    date3.Display();    //Copy constructor called
    cout<<endl;     //换行
 
    return 0;
}

注:在vscode中会出现一共只有4次 Copy constructor called 的情况,这是因为在 return newdate2 中不调用复制构造函数

但是在 vs2010 中是调用的

析构函数

  • 对象生命周期结束时,需要释放所占用的内存资源
  • 说明
  • 实现可以在类内,也可在类外
  • 函数名与类名相同,前面加“~”
  • 公有,无返回值类型
  • 无形参,不能被重载,有且仅有一个
  • 析构函数调用
  • 对象生命周期结束,系统自动调用
  • new动态创建的对象,用delete释放申请的内存
  • 析构函数的调用顺序永远与构造函数的调用顺序相反

代码实例

#include <iostream>
using namespace std;
 
class CDate 
{
private:
    int Date_Year, Date_Month, Date_Day;
 
public:
    CDate(int year=2021, int month=1, int day=1);
    ~CDate();
};
 
CDate::CDate(int year, int month, int day) : Date_Year(year), Date_Month(month), Date_Day(day) 
{
    cout<<"Constructor:"<<Date_Year<<"-"<<Date_Month<<"-"<<Date_Day<<endl;
}
 
CDate::~CDate() 
{
    cout<<"Destructor:"<<Date_Year<<"-"<<Date_Month<<"-"<<Date_Day<<endl;
}
 
int main() 
{
    CDate today;
    CDate tomorrow(2022, 1, 1);
    return 0;
}

析构函数与动态内存分配

#include <iostream>
#include <cstring>
using namespace std;
 
class CMessage
{
private:
    char *pmessage; //指向消息的指针
public:
    CMessage (const char *text="中国一点都不能少")
    {
        pmessage = new char[strlen(text)+1];    //申请动态空间
        strcpy_s(pmessage, strlen(text)+1, text);   //拷贝字符串到内存中
    }
    void show()
    {
        cout << pmessage << endl;
    }
    ~CMessage()
    {
        cout<<"Destructor called"<<endl;
        delete[] pmessage;   //释放动态空间
    }
};
 
int main() 
{
    CMessage message1;
    CMessage message2("Hello World!");
    CMessage *p = new CMessage("C++ is awesome!");
    message1.show();
    message2.show();
    p->show();
    delete p;
    return 0;
}

一定要记得最后要释放申请的动态内存空间

目录
相关文章
|
12月前
|
编译器 C++
类和对象(2):构造函数,析构函数
类和对象(2):构造函数,析构函数
|
11月前
|
编译器 C++
【C++】类和对象(中)之构造函数与析构函数
【C++】类和对象(中)之构造函数与析构函数
55 0
|
编译器 C++
C++类与对象 - 2(构造函数和析构函数)(超详细)
C++类与对象 - 2(构造函数和析构函数)(超详细)
65 0
|
6月前
|
编译器 C++
【C++类和对象】构造函数与析构函数
【C++类和对象】构造函数与析构函数
【C++类和对象】构造函数与析构函数
|
6月前
|
存储 编译器 对象存储
【C++】类与对象(构造函数、析构函数、拷贝构造函数、常引用)
【C++】类与对象(构造函数、析构函数、拷贝构造函数、常引用)
34 0
|
6月前
|
编译器 C语言 C++
【c++】类和对象(三)构造函数和析构函数
朋友们大家好,本篇文章我们带来类和对象重要的部分,构造函数和析构函数
|
6月前
|
存储 编译器 C语言
【C++】类和对象之构造函数、析构函数、拷贝构造函数(二)
【C++】类和对象之构造函数、析构函数、拷贝构造函数(二)
|
6月前
|
编译器 C++
C++——类和对象(构造函数与析构函数)
C++——类和对象(构造函数与析构函数)
|
11月前
|
存储 编译器 C++
类和对象:构造函数,析构函数与拷贝构造函数
类和对象:构造函数,析构函数与拷贝构造函数
|
11月前
|
编译器 程序员 C++
C++类和对象中(构造函数,析构函数,拷贝构造函数)详解(下)
C++类和对象中(构造函数,析构函数,拷贝构造函数)详解