在C++的类中,都会有一个或多个构造函数、一个析构函数、一个赋值运算操作符。即使我们自己定义的类中,没有显示定义它们,编译器也会声明一个默认构造函数、一个析构函数和一个赋值运算操作符。例如:

 //声明一个空类
class Empty{}; //但是这个空类和下面这个类是等同的
class Empty
{
Empty(){.....}; //默认构造函数
Empty( const Empty & rhs ){......} //复制构造函数
~Empty(){..........} //析构函数 Empty operator * (const Empty & rhs){.........}
};

  值得注意的是,只有当这些函数被调用的时候,他们才会被编译器创建出来。

  如果我们已经声明了一个构造函数,那么编译器将不会再创建一个默认构造函数。

  下面来详细介绍一下构造函数和析构函数。

1.构造函数

  构造函数(constructor)是与类同名的特殊成员函数,主要用于初始化对象的数据成员。定义形式如下:

 class  X
{
// .......
X(); //无参构造函数
X(......); //有参构造函数,构造函数支持重载 // .........
}

  

构造函数的声明和定义方法与类的其他成员函数相同,可以在类的内部定义构造函数,也可以先在类中声明构造函数,然后在类外进行定义。在类外定义构造函数的形式如下:

 X :: X(.....)
{
//...........
}

  构造函数具有以下几个特点:

  (1)构造函数与类同名

  (2)构造函数没有返回类型,void也不行

  (3)构造函数可以被重载

  (4)构造函数由系统自动调用,不允许在程序中显示调用它

  (5)构造函数的调用时机是定义对象之后的第一时间,即构造函数是对象的第一个被调用的函数

  (6)定义对象数组或用new创建动态对象时,也要调用构造函数。但定义数组对象时,必须有无参构造函数

  (7)构造函数通常应定义为共有成员(当然也可以定义为私有的,但不能被类外部访问。单例模式就用到私有化的构造函数)

  同时还需注意一下几点:

  (1)构造函数初始化列表中的成员初始化次序与它们在类中声明的次序相同,与其在初始化列表中的次序无关。如:

 Tdate::Tdate(int m , int d , int y):month(m),day(d),year(y){}
Tdate::Tdate(int m , int d , int y):year(y),month(m),day(d){}
Tdate::Tdate(int m , int d , int y):day(d),year(y),month(m){}
//以上三个构造函数完全相同

  (2)构造函数初始化列表先于构造函数体中的语句执行

  (3)以下类成员必须使用成员初始化列表进行初始化:常量成员、引用成员、类对象成员、派生类构造函数对基类构造函数的调用

1.1默认构造函数

  默认构造函数是指不需要显示提供参数的构造函数。在某些情况下,必须使用默认构造函数来定义对象(如对象数组)

  如果一个类没有定义任何构造函数,在需要时编译器将会为它生成一个默认构造函数,它只负责创建对象,不做任何初始化工作。

  在用默认构造函数创建对象时,如果创建的是全局对象或静态对象,则对象的位模式全为0(可以理解为将所有数据成员初始化为0);如果创建的是局部对象,不进行对象数据成员的初始化,对象数据成员是未知的。

  注意:只有在类没有定义任何构造函数时,系统才会产生默认构造函数。一旦定义了任何形式的构造函数,系统将不再产生默认构造函数。

  我们可以对默认构造函数进行重定义,来为对象的数据成员提供初始值。同时我们还可以为参数提供默认值。

1.2重载构造函数

  重载构造函数必须具有不同的函数原型(即参数个数、参数类型或参数次序不能完全相同)

1.3复制构造函数

  复制构造函数是一个特殊的构造函数,用于根据已存在的对象初始化一个新建对象。

  如果没有定义类的复制构造函数,在需要时,C++编译器将产生一个具有最小功能的默认复制构造函数,形式如:X::X(const X&){}

  默认复制构造函数以成员按位复制(bit-by-bit)的方式实现成员的复制。按位复制就是把一个对象各数据成员的值原样复制到目标对象中。在没有涉及指针类型的数据成员时,默认构造函数能够很好地工作。但是,当一个类有指针类型的数据成员时,默认复制构造函数常会产生指针悬挂问题。如果类存在指针类型的数据成员,就应该为他提供自定义的复制构造函数(也就是重载)

  注意:复制构造函数的参数常常是const类型的本类对象的引用(X::X(const X&){})

2.析构函数

  析构函数(destructor)是与类同名的另一个特殊成员函数,作用于构造函数相反,用于在对象生存期结束时完成对象的清理工作。

  析构函数的名字由“~”+“类名”构成,形式如下:

 class X
{
private:
//............
public:
~X(); //析构函数
X(); //无参构造函数
X(....); // 有参重载的构造函数
//.........
}

  析构函数具有以下特点

  (1)析构函数的名字是在类名前加上“~”,不能是其他名字

  (2)析构函数没有返回值类型(void也不行),没有参数表

  (3)析构函数不能重载,一个类只能有一个析构函数

  (4)析构函数只能由系统自动调用,不能再程序中显示调用析构函数

  (5)若有多个对象同时结束生存期,C++按照与调用构造函数相反的次序调用析构函数

  (6)每个类都应该有一个析构函数,如果没有显示定义析构函数,C++将产生一个最小化的默认析构函数(X::~X())

  (7)构造函数和析构函数都可以是inline函数

  (8)在通常情况下,析构函数应设置为公有成员

C++学习之类的构造函数、析构函数的更多相关文章

  1. C++基础学习9:构造函数和析构函数

    1.  构造函数用来对类对象进行初始化,它完成对内存空间的申请.赋初值等工作.  2.  析构函数主要是用来做清理工作的. 补充:函数名或变量名前面有"::"但是没有类名,说明这是 ...

  2. C++反汇编第一讲,认识构造函数,析构函数,以及成员函数

    C++反汇编第一讲,认识构造函数,析构函数,以及成员函数 以前说过在C系列下的汇编,怎么认识函数.那么现在是C++了,隐含有构造和析构函数 一丶认识构造函数 高级代码: class MyTest { ...

  3. C++构造函数/析构函数 设置成private的原因

    C++构造函数/析构函数 设置成private的原因 标签(空格分隔): c/c++ 将构造函数,析构函数声明为私有和保护的,那么对象如何创建? 已经不能从外部调用构造函数了,但是对象必须被构造,应该 ...

  4. Vue源码学习1——Vue构造函数

    Vue源码学习1--Vue构造函数 这是我第一次正式阅读大型框架源码,刚开始的时候完全不知道该如何入手.Vue源码clone下来之后这么多文件夹,Vue的这么多方法和概念都在哪,完全没有头绪.现在也只 ...

  5. C++ 类 & 对象-类成员函数-类访问修饰符-C++ 友元函数-构造函数 & 析构函数-C++ 拷贝构造函数

    C++ 类成员函数 成员函数可以定义在类定义内部,或者单独使用范围解析运算符 :: 来定义. 需要强调一点,在 :: 运算符之前必须使用类名.调用成员函数是在对象上使用点运算符(.),这样它就能操作与 ...

  6. C++学习笔记(1)-构造函数与析构函数

    1.C++规定,每个类必须有默认的构造函数,没有构造函数就不能创建对象. 2.若没有提供任何构造函数,那么c++自动提供一个默认的构造函数,该默认构造函数是一个没有参数的构造函数,它仅仅负责创建对象而 ...

  7. C++ 中的类构造函数 & 析构函数

    类的构造函数 类的构造函数是类的一种特殊的成员函数,它会在每次创建类的新对象时执行. 构造函数的名称与类的名称是完全相同的,并且不会返回任何类型,也不会返回 void.构造函数可用于为某些成员变量设置 ...

  8. c++基础语法 构造函数 析构函数 类的组合

    1 构造函数 1.不能指定任何返回值,甚至连void都不能有. 2.与Java不同,c++不同new对象,对于无参的构造函数声明对象时括号应该省略. 2 析构函数 1. 前加~,不能有参数,不能有返回 ...

  9. [ Java学习基础 ] Java构造函数

    构造方法是类中特殊方法,用来初始化类的实例变量,它在创建对象(new运算符)之后自动调用. Java构造方法的特点如下: 构造方法名必须与类名相同. 构造方法没有任何返回值,包括void. 构造方法只 ...

随机推荐

  1. hiho1093_spfa

    题目 SPFA模板题,题目中数据可能有两个点之间有多条边直接相连,使用 unordered_map< int, unordered_map< int, int>>, 来存储图的 ...

  2. Unity5.3官方VR教程-系列1

    如果你不是VR游戏或应用的开发者,可以选择无视下面的内容,这不是给普通用户看的~ 如果你之前曾经为Oculus Rift DK2或者Gear VR开发过,那么心里面一定曾经有千万个草泥马来回奔跑过.虽 ...

  3. Java多线程基础:进程和线程之由来

    转载: Java多线程基础:进程和线程之由来 在前面,已经介绍了Java的基础知识,现在我们来讨论一点稍微难一点的问题:Java并发编程.当然,Java并发编程涉及到很多方面的内容,不是一朝一夕就能够 ...

  4. Linq分页查询

    //Linq分页查询 int pageIndex = Convert.ToInt32(HttpContext.Current.Request["PageIndex"]); int ...

  5. HTML4 和 HTML5 的10个关键区别

    HTML5是HTML标准的下一个版本.越来越多的程序员开始HTML5来构建网站.如果你同时使用HTML4和HTML5的话 ,你会发现用HTML5从头构建,比从HTML4迁移到HTML5要方便很多.虽然 ...

  6. 网络与RPC

    网络与RPC 标签 : Java基础 Java为网络编程提供的java.net包封装了底层通信细节, 包含了大量的基础组件以及TCP/UDP协议的编程接口, 使得开发者可以专注于解决问题, 而不用关注 ...

  7. C# winform程序怎么打包成安装项目(图解)

    1:新建安装部署项目 打开VS,点击新建项目,选择:其他项目类型->安装与部署->安装向导(安装项目也一样),然后点击确定.(详细见下图) 此主题相关图片如下: 2:安装向导 关闭后打开安 ...

  8. Linux基础: 挂载镜像文件(Mount & ISO)

    ISO/Ghost 镜像文件概念(裸机安装,无光驱安装,跨平台安装) ISO是镜像文件:所谓镜像文件其实和ZIP压缩包类似,它将特定的一系列文件按照一定的格式制作成单一的文件,以方便用户下载和使用,例 ...

  9. 自定义头文件 No such file or directory

    my_file.h为你的头文件名 要用#include"my_file.h",而不能是#include<my_file.h>. 如果头文件名在尖括号<>里, ...

  10. Tomcat数据库连接池的配置方法总结

    Tomcat数据库连接池的配置方法总结 数据库连接是一种关键的有限的昂贵的资源,这在多用户网页应用程序中体现的尤为突出.对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性能指标 ...