C++学习笔记(二)——构造函数和析构函数

C++学习笔记(二)——构造函数和析构函数

我的博客:竹山听雨


当建立一个对象时,对象的状态(数据成员的取值)是不确定的。构造函数是C++中一个特殊的成员函数,它可自动进行对象的初始化。而析构函数在对象撤销时执行清理任务,进行善后处理

特性

  • 没有返回值说明,也就是定义构造函数和析构函数不能指出函数返回值得类型,void也不能有

  • 它们不能被继承

  • 构造函数可以有缺省常熟

  • 析构函数可以是虚的,单构造函数不可以是虚的

  • 不可取他们的地址

  • 不能用常规调用方法调用析构函数,当使用完全的限定名(带对象名。类名和函数名)时,可以调用析构函数

  • 当定义对象时,编译程序自动调用构造函数,当删除对象时,编译程序自动地调用析构函数

构造函数

对象的初始化是指对象数据成员的初始化,在使用对象前,一定要初始化,但因为数据成员一般为私有的(private),所以不能直接赋值。

一种方法是类中提供一个普通成员函数来初始化,但是可能会造成使用不便(使用对象前必须显式调用该函数)和不安全(未调用初始化函数就使用)

另一种方法就是使用了构造函数对对象进行初始化。

定义: 构造函数是一个与类同名,没有返回值的特殊成员函数。构造函数既可在类外定义,也可以作为内联函数在类内定义。

使用: 在定义该类对象时,可以将参数传递给构造函数来初始化对象。一般用于初始化类的数据成员,每当创建一个对象时(包括用new动态创建),会自动调用构造函数

声明: <类名>::构造函数

//类内定义
class Student{
    public:
    Student(int id,string name)
    {
        ...
    }
    ...
}
//类外定义
class Student{
    public:
    Student();
    ...
}
Student::Student(int id,string name)
    {
        ...
    }
//调用:
int main()
{
    Student s1(2,"bamboosir920");
    return 0;
}

注意: 构造函数也可以进行重载,构造函数也可以使用缺省参数

缺省构造函数(默认构造对象)

功能: 缺省构造参数是个无参构造函数,它仅负责创建对象,而不做任何初始化

背景: C++规定,每个类必须有一个构造函数,没有构造函数,就不能创建任何对象。若用户未显式定义一个类的构造函数,则提供给一个缺省的构造函数

eg:

class test{
    public:
    test();
    test(int n);
}
test::test()
{
    cout<<"xxx";
}
test::test()
{
    cout<<"xxx"
}
int main()
{
    test x;//调用无参数的构造函数
    test y(2);//调用带两个参数的构造函数
}

创建对象数组

test stu[5]={test(2),test(3),test(4),test(5),test(1)}

拷贝构造函数(复制构造函数)

功能: 是用一个已有的对象来初始化一个被创建的同类对象,是一种特殊的构造函数,具有一般构造函数的所有特性

特点: 其形参是本类对象的引用

声明:类名(类名& 对象名)

class Student{
    public:
    Student();
    Student(Student &);//拷贝构造函数的声明
    private:
    int id;
    String name;
    double score;
    ...
}
Student::Student(Student &other)
{
    id=other.id;
    name=other.name;
    score=other.score;
}

以下四种情况会自动调用拷贝构造函数

方法1
Student s1;
Student s2(S1);
方法2

用类的一个对象去初始化另一个对象的

Student s2=s1;
方法3

对象作为函数参数传递时,调用拷贝构造函数

void f(Student a){} //定义f函数,形参为Student类对象
Student b;
f(b);
方法4
Student f()  //定义f函数,返回值为Student类对象
{
    Student a;
    ...
    return a;
}
Student b;
b=f();

深拷贝构造函数和浅拷贝构造函数

区别:

  • 浅拷贝,即只复制对象空间,不复制对象资源
  • 深拷贝,既复制对象空间,又复制资源

默认提供的构函数只是对对象进行浅拷贝

一般情况下,只需要使用系统提供的浅拷贝构造函数即可,但是如果对象的数据成员包括指向堆空间的指针,就不能使用这种拷贝方式,因为两个对象都拥有一个同一个资源,因此必须自定义构造函数

条件:

  • 肯定要调用拷贝构造函数
  • 数据成员包括指向堆内存的指针
class test{
    public:
    test(char *na) //构造函数
    {
        name=new char[strlen(na)+1];
        if(name!=0)
        {
            strcpy(name,na);
        }
        ...
    }
    test(test& p) //深拷贝构造函数
    {
        name=new char[strlen(p.name)+1]; //复制资源
        if(name!=0)
        {
            strcpy(name,p.name); //复制对象资源
        }
    }
    ~test(){delete name;} //析构函数
    private:
    char* name;
}
int main()
{
    test a("su");
    test li(a);
    return 0;
}

当在main()中调用了深构造函数,如果却没有定义深构造函数,就会默认调用缺省的浅拷贝构造函数,就会发生报错

当数据成员有使用new动态分配内存空间,在析构函数中使用delete进行动态内存空间的释放以及赋值=运算符进行重载,应该自定义深拷贝构造函数

构造函数对数据成员的初始化

构造函数可以采用以下几种不同的形式对数据成员进行初始化

在构造函数的函数体中进行初始化
void test(int sid,string sname)
{
    id=sid;
    name=sname;
}
使用构造初始化表对数据成员进行初始化
<类名> ::<构造函数>(<参数表>):<变量1>(<初值1),....<变量n>(<初值n>)

{…}

注意:

  • 数据成员初始化的持续取决于他们在类定义中的声明次序,与他们在成员初始化表中的次序无关
  • 常量和引用的初始化必须放在构造函数正在建数据成员结构的时候,也就是放在构造函数的冒号后面
class test
{
 public:
    test(int sid,string sname):id(sid),name(sname)
    {}
 private:
    int id;
    string name;
}

类类型和基本数据类型的转换

构造函数用作类型转换

前提: 此类一定是只带一个参数的构造函数

class A
{
    public:
    A();
    A(int);
}
类类型转换函数

在函数体中声明

operator type();

type为要转换的基本类型名,既没有参数也没有返回类型,但是在函数体重必须具有一个type类型的对象

定义转换函数的函数体

类名::opertor type()
{
    ...
    return type 类型的值
}

使用类型转换函数

析构函数

功能: 当对象被撤销时,释放该对象占用的空间

作用: 当对象消亡时,系统将自动调用析构函数,执行一些在对象撤销前必须执行的清理任务

特点:

  • 不能有任何的返回类型,也不能使用void
  • 析构函数没有参数,每个类只能有一个析构函数
  • 析构函数的函数名为~类名
  • 析构函数即可以系统自动调用也可以手工调用

自动调用的三种情况:

  • 一个动态分配的对象被删除,即使用delete删除对象时,编译系统会自动调用析构函数

  • 程序运行结束时

  • 一个编译器生成的临时对象不再需要时

析构函数的手工调用

对象名.类名::析构函数名

析构函数与构造函数的调用顺序

先构造后析构

class A
{
    public:
    A(){..}
    A(A & S){...} //拷贝构造函数
    ~A(){
        cout<<<"删除";
    }
    ...
}
int main(){
    A X();
    A y(x); //拷贝构造
    return 0;
    //函数运行结束,先析构x,再析构y
}

猜你喜欢

转载自blog.csdn.net/InkBamboo920/article/details/106280360
今日推荐