1 转换构造函数


    C++的转换构造函数是只有一个参数的构造函数。当程序试图将一个其他类型的对象或基本类型值赋给该类的一个待初始化对象时(如Person p=”Dean”;),就会尝试调用转换构造函数。
    转换构造函数可以通过设置默认值的方法同无参构造函数在同一函数体内进行定义。定义语句形式如下:

   1: <类型名> ( <参数类型>  参数名 =  <参数默认值> )

   2: {

   3:     //函数实现

   4: }

2 拷贝构造函数

    拷贝构造函数是用一个对象来初始化另一个对象的构造函数。构造函数的参数是该类对象的一个常引用。拷贝构造函数会在以下三种情况下被调用:

    (1)用类的一个对象去初始化另一个对象。

    (2)函数的形参是类对象,调用函数时形参和实参结合会调用拷贝构造函数。

    (3)函数的返回值是一个类对象,返回时会用拷贝构造函数构造一个临时对象。

    拷贝构造函数的定义形式为:

   1: <类型名>( const  <类型名>&  <参数名> )

   2: {

   3:     //函数实现

   4: }

3 赋值运算符重载

    赋值运算符的重载是为了实现将一个对象赋给另一个对象。如果编程人员不实现赋值运算符的重载,系统会自动生成一个版本。

    赋值运算符重载需要一个参数,该参数是对另一个类对象的常引用,返回值是对象本身的引用。其定义形式如下:

   1: <类型名>&  operator = ( const <类型名>&  <参数名> )

   2: {

   3:     //函数实现

   4: }

4 程序实例

    先定义一个Person类:

   1: #include <iostream>

   2: #include <string>

   3: int No=1;

   4: class Person

   5: {

   6: public:

   7:     Person(std::string name="Unknown")

   8:     {

   9:         if(name=="Unknown")

  10:             std::cout<<"无参构造函数被调用! ";

  11:         else

  12:             std::cout<<"类型转换构造函数被调用! ";

  13:         this->name=name;

  14:         this->no=No++;

  15:         std::cout<<name<<" "<<no<<std::endl;

  16:     }

  17:     Person(const Person &P)

  18:     {

  19:         std::cout<<"拷贝构造函数被调用! ";

  20:         this->no=P.no+10;

  21:         this->name=P.name;

  22:         std::cout<<name<<" "<<no<<std::endl;

  23:     }

  24:     Person& operator =(const Person p)

  25:     {

  26:         std::cout<<"重载运算符=被重载! ";

  27:         this->name=p.name;

  28:         this->no=p.no;

  29:         std::cout<<name<<" "<<no<<std::endl;

  30:         return *this;

  31:     }

  32:     ~Person()

  33:     {

  34:         std::cout<<"析构函数被调用! ";

  35:         std::cout<<this->name<<" "<<this->no<<std::endl;

  36:     }

  37:     void Output()

  38:     {

  39:         std::cout<<"此处调用Output方法输出:";

  40:         std::cout<<name<<"  "<<no<<std::endl;

  41:     }

  42: private:

  43:     int no;

  44:     std::string name;

  45: };

    下面是具体的调用方法:

   1: #include "Person.h"

   2: Person Output(Person p)

   3: {

   4:     p.Output();

   5:     std::cout<<"-------------------------------------------"<<std::endl;

   6:     return p;

   7: }

   8: int main()

   9: {

  10:     Person p1;

  11:     std::cout<<"==========================================="<<std::endl;

  12:     Person p2="Dean";

  13:     std::cout<<"==========================================="<<std::endl;

  14:     p1=Output(p2);

  15:     std::cout<<"==========================================="<<std::endl;

  16:     Person p3(p2);

  17:     system("pause");

  18:     return 0;

  19: }

    运行的结果如下:

    程序的执行顺序如下:

    (1)调用了无参构造函数,默认给p1对象的name赋值为Unknown,no赋值为1。

    (2)用字符串常量“Dean”来初始化对象p2,此处调用了转换构造函数。

    (3)调用Output函数。该过程比较复杂,其中的详细执行过程包括:

            a)形参和实参结合,系统会复制p2作为参数。此时会调用Person类的拷贝构造函数,通过输出可以看到该临时对象是p2的一个副本。

            b)调用p2副本的Output方法输出。

            c)返回阶段。由于返回值是一个Person类的对象,所以会生成一个临时对象作为返回值,而返回值是通过拷贝构造函数复制了参数的各成员。由函数定义可以看到,main函数调用的Output函数实际上返回的是参数的一个副本,也就是穿进去的实参p2的副本的副本,临时对象在调用拷贝构造函数时输出的no为22也说明了这一点。

    (4)将Output函数的返回值赋给p1。p1获取了p2副本的副本的各成员后该临时对象就析构了。

    (5)用p2来初始化p3。这是拷贝构造函数的最普通的应用,通过输出可以看到p3是p2的一次拷贝。

C++的转换构造函数、拷贝构造函数、赋值运算符重载的更多相关文章

  1. C++构造函数 & 拷贝构造函数 & 派生类的构造函数 & 虚继承的构造函数

    构造函数 ,是一种特殊的方法 .主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中 .特别的一个类可以有多个构造函数 ,可根据其参数个数的不同或参数 ...

  2. C/C++(C++拷贝构造器,赋值运算符重载)

    拷贝构造器 由己存在的对象,创建新对象.也就是说新对象,不由构造器来构造,而是由拷贝构造器来完成.拷贝构造器的格式是固定的. class 类名 { 类名(const 类名 & another) ...

  3. C++中构造函数,拷贝构造函数和赋值函数的区别和实现

    C++中一般创建对象,拷贝或赋值的方式有构造函数,拷贝构造函数,赋值函数这三种方法.下面就详细比较下三者之间的区别以及它们的具体实现 1.构造函数 构造函数是一种特殊的类成员函数,是当创建一个类的对象 ...

  4. C++中的构造函数,拷贝构造函数,赋值函数

    C++中一般创建对象,拷贝或赋值的方式有构造函数,拷贝构造函数,赋值函数这三种方法.下面就详细比较下三者之间的区别以及它们的具体实现 1.构造函数 构造函数是一种特殊的类成员函数,是当创建一个类的对象 ...

  5. 如何避免被C++默认拷贝构造函数忽悠?

    一.背景介绍           因为工作关系,需要用到C++编程.对于我来说,虽然一直从事的是linux平台下的嵌入式软件开发,但深入用到C++的特性的地方并不多.对于C++,用得最多的无非是指针. ...

  6. C++对象模型的那些事儿之四:拷贝构造函数

    前言 对于一个没有实例化的空类,编译器不会给它默认生成任何函数,当实例化一个空类后,编译器会根据需要生成相应的函数.这类函数包括一下几个: 构造函数 拷贝构造函数 析构函数 赋值运算符 在上一篇博文C ...

  7. C++构造函数和拷贝构造函数详解

    构造函数.析构函数与赋值函数是每个类最基本的函数.它们太普通以致让人容易麻痹大意,其实这些貌似简单的函数就象没有顶盖的下水道那样危险. 每个类只有一个析构函数和一个赋值函数,但可以有多个构造函数(包含 ...

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

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

  9. C++基础 (3) 第三天 构造函数 构造函数初始化列表 拷贝构造函数 析构函数 静态成员变量

    // 同类之间无私处 2构造函数 3析构函数 4构造函数的种类和析构函数的顺序 结论:析构函数的调用顺序,跟对象的构造顺序相反,谁先构造,谁最后一个被析构. 拷贝构造函数: 注意: 等号写在下面和写在 ...

随机推荐

  1. 如何写出性能好的sql

    开发人员是很少注意SQL对数据库性能影响的重要性的,大多程序员都会认为SQL是比较简单的,需要的时候查查手册就可以了,很少有深究的. 这样的观念对大型系统的开发是致命的,需要纠正这样的观念. 造成这样 ...

  2. Android实例-多窗口的切换(XE8+小米2)

    1.图片一是程序运行后的界面. 2.图片二是点击"非模态显示"的界面. 3.图片三是点击"模诚显示"的界面(提示平台不支持). unit Unit1; inte ...

  3. [C语言 - 11] 语言编译执行

    使用gcc编译器 1.预编译 gcc -E Hello.c -o Hello.i 2.汇编 gcc -S Hello.i -o Hello.s   3.编译 gcc -c Hello.s -o Hel ...

  4. SQL函数中的动态执行语句

    一.为什么要使用动态执行语句? 由于在PL/SQL 块或者存储过程中只支持DML语句及控制流语句,并不支持DDL语句,所以Oracle动态执行语句便应允而生了.关于DDL与DML的区别,请参见:DDL ...

  5. mysql之数据库备份与恢复

    备份与恢复 系统运行中,增量备份与整体备份. 例如:每周日整体备份一次,周一到周六只备份当天. 如果周五的数据出了问题,可以用周日的整体+周一.周二.周三.周四来恢复. 备份的工具: 有第三方的收费备 ...

  6. JavaScript Source Map 详解

    源码地址: http://www.ruanyifeng.com/blog/2013/01/javascript_source_map.html 上周,jQuery 1.9发布. 这是2.0版之前的最后 ...

  7. 对PostgreSQL的prepared statement的深入理解

    看官方文档: http://www.postgresql.org/docs/current/static/sql-prepare.html PREPARE creates a prepared sta ...

  8. 禁止UINavigationController 左滑 返回的效果

    在iOS7中,新增加了一个小小的功能,也就是这个:self.navigationController.interactivePopGestureRecognizer.enabled = YES;

  9. thinPHP中多维数组的遍历

    $drug=array(    'ACEI'=>array(array('ch_name'=>'卡托普利','en_name'=>'captopril'),array('ch_nam ...

  10. XML文件

    XML 指可扩展标记语言(eXtensible Markup Language) XML 被设计用来传输和存储数据. 什么是 XML? XML 指可扩展标记语言 XML 是一种标记语言,非常类似 HT ...