前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++:构造函数与析构函数

C++:构造函数与析构函数

作者头像
字节星球Henry
发布2021-08-09 16:47:58
5240
发布2021-08-09 16:47:58
举报

构造函数

构造函数用于对象的初始化,一旦建立对象,就需要有一个有意义的初始值,构造函数的作用即是在对象初始化时被调用,给对象分配内存空间以及完成初始化。

变量和结构体的初始化方法如下:

代码语言:javascript
复制
int a = 1;//变量的初始化
int b = 2;
int *p = &a;
代码语言:javascript
复制
struct instance {
    int num;
    string name;
};
void fun(){
    instance s = {50 ,"Henry"};//结构体初始化
}

但是对于对象而言,这种初始化方法显然不可取,因为类中的 private 和 protected 成员外界并不能对其访问:

代码语言:javascript
复制
class instance{
    public:
        //....
    private:
        int num;
        string name;
};
void fun {
    instance s = {50,"Henry"}//error
} 

这样的初始化操作意味着在其他函数中允许访问类对象中的保护数据成员,然而类的封装性就体现在有一部分被封装的数据外界是不能对其进行访问的,该行为被编译器禁止。

所以,在初始化对象时,常常使用构造函数来对受保护的数据成员进行初始化操作:

代码语言:javascript
复制
class instance
{
public:
    instance() //构造函数与类同名,无返回类型,也不允许return
    {
        test = 55;
        name = "Hello World";
    }
    void print()
    {
        cout << "tset:" << test1 << ",name:" << name << endl;
    }

private:
    int test;
    string name;
};
int main()
{
    auto pointer = new instance();//调用构造函数instance()
    pointer->print();
    delete pointer;
    return 0;
}

程序将输出 :tset:55,name:Hello World

刚才演示的是构造函数的类内定义,同样的,构造函数也允许类外定义,但要注意,构造函数的类外定义和普通的成员函数的类外定义一样,需要在函数名前面加上 类名:: 为了区分成员函数与其他普通函数,故该操作是必要的。

代码语言:javascript
复制
class instance{
    public:
        instance();//构造函数声明
        //...
    private:
        //...
};
void fun(){
    instance::instance(){//构造函数的类外定义
        //.....
    }
}

以上为构造函数类外定义演示。

对于对象数组,声明时,数组成员有多少个,就会调用多少次的构造函数,来分别初始化数组中每一个成员:

代码语言:javascript
复制
void fun() {
    instance temp[5];//对象数组,5个成员
    //..
}

以上就会调用五次 instance 的构造函数,来分别初始化 temp0,temp1......

那么,如果一个类的对象是另一个类的数据成员,在进行另一个类的对象初始化时,会对该成员自动调用其构造函数,每个类只复制处理自己的对象,其它对象就由它所属类的构造函数来进行处理。

注意:若一个类中有某些数据成员是另一个类的对象,那么在调用这个类的构造函数时,该构造函数会先调用另一个类的构造函数将这些对象初始化后后再执行自己的函数体对该对象进行初始化。

析构函数

说简单点就是和构造函数有着相反的作用,析构函数用于初始化而析构函数用于在对象销毁前将构造函数申请的资源释放。可以理解为用 new 申请堆内存后需要使用 delete 对其进行释放,析构函数的作用相当于 delete。

正是由于析构函数的此特点,所以它的定义与构造函数的区别仅为一个逻辑非运算符,即:~

代码语言:javascript
复制
class instance{
    public:
    instance(){
    name =  new char[20];
}
    ~instance(){
    delete[] name;//释放申请的堆空间
    name = nullptr;
}

析构函数在对象生命周期时会依次调用,且调用顺序与构造函数相反,即先初始化的对象后释放。

带参数的构造函数

前面介绍的构造函数都是无参构造函数,它有时并不能满足我们的要求,它只能机械地去初始化一个对象。

对于以下的实例,我们就需要使用含参的构造函数:

代码语言:javascript
复制
class Mankind{
    public:
    //..
    private:
        int age;
        int sex;
        Date birthday;
};

众所周知,每个人有每个人的特点,如果该构造函数依旧是无参类型的,那么我们初始化的对象将是千篇一律。

其次,构造函数可以重载,显式调用构造函数将产生一个无名对象,无名对象将在之后介绍。

代码语言:javascript
复制
class Mankind{
    public:
        Mankind(string n, int a, int s, Date b)
        {
            name = n;
            age = a;
            sex = s;
            birthday = b;
}
    private:
        string name;
        int age;
        int sex;
        Date birthday;//Date为另一个类
};

这样,我们就可以根据不同人的特点,使用不同的参数,初始化不同的对象。

默认构造函数

C++ 规定每一个类都必须有一个构造函数,如果没有定义构造函数,系统将调用默认的构造函数(等价于定义一个空的构造函数)。

默认构造函数仅复制创建对象所需空间,不提供任何初始化工作,当然如果一个类中定义了构造函数,系统将不在提供该默认构造函数,如需要在定义有参构造函数后使用无参构造函数,那么需要自己定义同名的无参构造函数。

我们在定义有参构造函数后需要注意以下问题:

代码语言:javascript
复制
class student{
    public:
        student(string nName){
          name = nName;
        }
    private:
        string name;
        //..
};
int main() {
    student noName;//error,没有与其匹配的构造函数
}

在初始化对象 noName 时,我们没有传入任何参数,但在类中我们却定义了需要 string 型参数的构造函数,所以系统不再提供无参的默认构造函数,编译器因此报错。

对类进行以下处理即可解决该问题:

代码语言:javascript
复制
class student{
    public:
        student(string nName){
          name = nName;
        }
        student(){}
    private:
        string name;
        //..
};

我们自行定义一个无参的空构造函数即可,之前我们也说到:系统调用默认的构造函数等价于定义一个空的无参构造函数。

最后,在创建无参对象时请勿在后面加括号,因为这会与定义一个返回类对象的无参函数混淆:

代码语言:javascript
复制
void fun(){
    student stu;//正确的无参对象声明方式
    student stu();//错误的无参对象声明方式
}

编辑:Henry 2021-02-03 转载前请申请

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 构造函数
  • 析构函数
  • 带参数的构造函数
  • 默认构造函数
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档