当前课程知识点:C++语言程序设计基础 >  第4章 类与对象 >  构造函数 >  复制构造函数

返回《C++语言程序设计基础》慕课在线视频课程列表

复制构造函数在线视频

复制构造函数

复制构造函数

复制构造函数定义

复制构造函数是一种特殊的构造函数,其形参为本类的对象引用。作用是用一个已存在的对象去初始化同类型的新对象。

class类名 {

public :

   类名形参);//构造函数

   类名(const 类名 &对象名);//复制构造函数

    //      ...

}

类名::类(const  类名&对象名)//复制构造函数的实现

{   函数体   }

隐含的复制构造函数

l  如果程序员没有为类声明拷贝初始化构造函数,则编译器自己生成一个隐含的复制构造函数。

l  这个构造函数执行的功能是:用作为初始值的对象的每个数据成员的值,初始化将要建立的对象的对应数据成员。

“=delete”

l  如果不希望对象被复制构造

n    C++98做法:将复制构造函数声明为private,并且不提供函数的实现。

n  C++11做法:用“=delete”指示编译器不生成默认复制构造函数。

l  例:

class Point {   //Point 类的定义

public:

    Point(int xx=0, int yy=0) { x = xx; y = yy; }    //构造函数,内联

    Point(const Point& p) =delete;  //指示编译器不生成默认复制构造函数

private:

    int x, y; //私有数据

};

复制构造函数被调用的三种情况

l  定义一个对象时,以本类另一个对象作为初始值,发生复制构造;

l  如果函数的形参是类的对象,调用函数时,将使用实参对象初始化形参对象,发生复制构造;

l  如果函数的返回值是类的对象,函数执行完成返回主调函数时,将使用return语句中的对象初始化一个临时无名对象,传递给主调函数,此时发生复制构造。

n  这种情况也可以通过移动构造避免不必要的复制(第6章介绍)

 



下一节:复制构造函数调用举例

返回《C++语言程序设计基础》慕课在线视频列表

复制构造函数课程教案、知识点、字幕

大家好

欢迎回来继续学习

C++语言程序设计

这一节我们来学习复制构造函数

复制构造函数是什么呢

为什么我们需要复制构造函数呢

我们还是首先温故而知新

回忆一下

当我们定义一个

基本类型的变量的时候

是不是经常会用一个已经存在的

已经有值的这个变量

去初始化新定义的变量

我们定义对象的时候

也会经常有这样的需求

就是用一个已经存在的对象

去初始化新对象

这个时候

怎么实现这种初始化呢

像基本类型的数据

怎么样用已经有值的变量

去初始化同类型的新变量

这个编译器它能知道

因为什么

因为基本类型数据

是语法预先定义好的

而我们自定义的类的类型

它该怎么初始化

当然编译器不会默认知道的

这个时候怎么用一个对象

去复制新对象

就需要由我们自己来定义

C++语法为我们提供了一种

特殊的构造函数

叫做复制构造函数

在复制构造函数中

我们可以规定

如何用一个已经存在的对象

去初始化一个新对象

这个已经有了对象

可以用它的引用作为

构造函数的参数

当然了

我们在前面例子中

看到有些类的定义

并没有定义复制构造函数

那么如果我们不定义

复制构造函数会怎么样呢

如果你在定义类的时候

没有定义复制构造函数

编译器也会为我们生成一个

默认的复制构造函数

那么这个默认的复制构造函数

它干事吗

会不会也像默认的构造函数似的

什么初始化工作都不做呢

不是的

默认的复制构造函数

它还真干事

它会实现两个对象的

数据成员之间的一一对应复制

那么这样的一一对应复制

很多时候就已经令人满意了

那么我们就不用写

复制构造函数了

但是在一些时候呢

这个默认的复制构造函数

还不那么令人满意

那么这时候我们就可以利用

复制构造函数这个机制

我们自己来规定

如何进行复制构造

现在我们就来看看

程序中如何自己定义

复制构造函数

复制构造函数它是一种

特殊的构造函数

它的形参必须是本类对象的引用

那么复制构造函数的作用

就是用这个形参构造新的对象

那我们来看

在类里面

我们可以定义普通的构造函数

它的函数名就是类名

有一个形参表

这个形参表

可以是任意格式的形参

任意类型的形参

任意个数的形参都可以

但是接下来我们来看

另一个构造函数就很特殊了

它的参数类型

必须是本类对象的引用

而在这个参数前面呢

又加了一个const来限定

为什么

因为我们在第三章中学过

当我们传递引用作为参数的时候

实际上是可以双向传递数据的

也就是说

接收这个引用参数的函数

它在函数体中

如果对这个形参引用

做了任何修改

那么实参也会被同步修改

显然这不是我们写

复制构造函数的目的

我们写复制构造函数

是希望用形参引用

所指的那个对象

去初始化新对象

但绝不希望在这个初始化过程中

把原有的那个形参对象给修改了

那么怎么办呢

在这加一个const关键字

这就说明了这个引用

是一个常引用

我们只能使用这个引用

去读取它里面的数据

但是不能用这个引用

对它指向的对象进行修改

这样既能够传参数进来

又能够保证实参的安全性

接下来我们看

这个复制构造函数

在类外实现的时候

它跟其他的构造函数

实际上是一样的

前面要有个类名

后面函数名

复制构造函数的函数名也是类名

同样它不允许定义返回值

函数体中也不允许有return语句

除了在构造新对象的时候

用已有的对象做参数

去初始化它

这种情况以外

还有什么情况下

复制构造函数有可能被调用呢

一共有三种情况

是典型的要调用

复制构造函数的情况

我们来看看哪三种情况

首先当然就是我们知道的

定义一个对象的时候

用本类的另外一个对象

作为初始值

这个时候显然是发生了复制构造

第二种情况呢

就是如果一个函数的参数

是类的对象

那形参首先规定

它是一个类的对象

那么调用函数的时候呢

给出的实参

也应该是同类型的对象

这个时候用实参去初始化形参

做形实结合的时候

就发生了复制构造

还有一种情况

就是如果一个函数的返回值

是类的对象

函数执行完了要返回主调函数了

这个时候它有一个return语句

return语句中返回一个对象

给主调函数

那么在这个过程中

也是有可能发生复制构造的

如果我们在定义一个类的时候

没有为它定义复制构造函数

这个时候编译的时候

编译器就会生成一个

默认的复制构造函数

这个默认的复制构造函数的功能

就是用参数引用

所指向的这个对象

去初始化新对象

直接将数据成员一一对应

就这么一一对应着复制

很多时候呢

这样的功能也就够用了

在这一章呢

我们遇到的例题习题都比较简单

大家会直觉地感觉

这个默认的复制构造函数

就挺好用了

那我们还需要自己定义

复制构造函数吗

如果现在你写简单程序的时候

觉得自定义复制构造函数

没有必要

用默认就挺好

那你可以先这样用

后面当我们在第六章的时候

我就会给大家看相关的例题

如果类的成员中有指针的时候

很多情况下

默认的复制构造函数

它实现的浅层复制功能

就不够用了

这时候我们就需要做

深层的复制构造

那即使对于简单的程序

我们也可以再想一想

会不会

你有不同的复制构造的需求呢

比如说我们使用复印机的时候

有可能是要缩小复印

放大复印

把彩色的复印成黑白的

或者说覆盖住一部分

复印另一部分 都有可能

这是平常我们

进行复印的时候的经验

在程序中

当我们复制一个对象的时候

是不是也有可能说

我要做特定功能的复制构造

并不希望

原样不动地一一对应复制

而是只复制它的一部分功能

或者复制的时候

给它做一个小小的修改

我们可以说

这是个打引号的复制

只要你使用复制构造函数

就可以按照你自己的意愿

你自己的需求

去定义你认为合适的复制方式

而默认的复制构造函数

就是原样照应

有时候呢

我们不希望对象被复制构造

那这个时候

按照C++98标准的做法

我们就可以将复制构造函数

声明为私有的private类型

并且不提供函数体的实现

在C++11中有更好

更方便的办法

就是用delete关键字

来指示编译器

不生成默认的复制构造函数

现在我们看点类的定义

我们把它简化了

大家看

这里面只有一个构造函数

然后另外在复制构造函数之后

有一个等于delete

这个就是指示编译器

不要生成默认的复制构造函数

C++语言程序设计基础课程列表:

第1章 绪论

-导学

--第1章导学

-计算机系统简介

--计算机系统简介

--计算机系统简介 测试题

-计算机语言和程序设计方法的发展

--计算机语言和程序设计方法的发展

--计算机语言和程序设计方法的发展 测试题

-面向对象的基本概念

--面向对象的基本概念

--面向对象的基本概念 测试题

-程序的开发过程

--程序的开发过程

--程序的开发过程 测试题

-信息的表示和储存

--计算机中的信息与存储单位

--计算机的数字系统

--数据的编码表示

--信息的表示和储存 测试题

-实验指导

--实验一:VS开发环境介绍

第2章 C++简单程序设计(一)

-导学

--第二章导学

-C++语言概述

--C++的特点和程序实例

--C++字符集和词法记号

--C++语言概述 测试题

-基本数据类型、常量、变量

--基本数据类型、常量、变量

--程序举例

--基本数据类型、常量、变量 测试题

-运算与表达式

--算术运算与赋值运算

--逗号运算、关系运算、逻辑运算和条件运算

--Sizeof运算、位运算

--运算优先级、类型转换

--运算与表达式 测试题

-实验二:简单程序设计(上)

--实验二:简单程序设计(上)

第2章 C++简单程序设计(二)

-数据的输入和输出

--数据的输入和输出

--数据的输入和输出 测试题

-选择结构

--if语句

--switch语句

--选择结构 测试题

-循环结构

--循环结构——while语句

--do-while语句

--for语句

--嵌套的控制结构、其他控制语句

--循环结构 测试题

-自定义类型

--自定义类型

--自定义类型

-第2章小结

--第二章小结

-实验二:C++简单程序设计(下)

--实验二C++简单程序设计(下)

第3章 函数

-导学

--导学

-函数定义

--函数定义

--函数定义 测试题

-函数调用

--函数调用(例3-1)

--例3-2

--例3-3

--例3-4

--例3-5

--例3-6

--函数调用 测试题

-嵌套与递归

--函数的嵌套调用(例3-7)

--函数的递归调用(例3-8)

--例3-9

--例3-10

--嵌套与递归 测试题

-函数的参数传递

--函数的参数传递

--函数的参数传递 测试题

-引用类型

--引用类型(例3-11)

--引用类型 测试题

-含有可变参数的函数

--含有可变参数的函数

--含有可变参数的函数 测试题

-内联函数

--内联函数(例3-14)

--内联函数 测试题

-constexpr函数

--constexpr函数

--CONSTEXPR函数课后习题

-带默认参数值的函数

--带默认参数值的函数

--默认参数值例(3-15)

--带默认参数值的函数 测试题

-函数重载

--函数重载(例3-16)

--函数重载 测试题

-C++系统函数

--C++系统函数(例3-17)

--C++系统函数习题

-第3章小结

--第三章小结

-实验三(上)函数的应用

--实验三(上)函数的应用

-实验三(下)函数的应用

--实验三(下)函数的应用

第4章 类与对象

-导学

--导学

-面向对象程序的基本特点

--面向对象程序的基本特点

--面向对象程序的基本特点 测试题

-类和对象

--类和对象的定义

--类和对象的程序举例

--类和对象 测试题

-构造函数

--构造函数基本概念

--构造函数例题(1)——例4-1

--构造函数例题(2)——例4-2

--委托构造函数

--复制构造函数

--复制构造函数调用举例

--构造函数 测试题

-析构函数

--析构函数

--析构函数 测试题

-类的组合

--类的组合

--类的组合程序举例

--前向引用声明

--类的组合 测试题

-UML简介

--UML简介

--UML简介课后习题

-结构体与联合体

--结构体(例4-7)

--联合体(例4-8)

--结构体与联合体 测试题

-枚举类

--枚举类

--枚举类 测试题

-第4章小结

--第四章小结

-实验四(上)

--实验四(上)

-实验四(下)

--实验四(下)

第5章 数据的共享与保护

-导学

--导学

-标识符的作用域与可见性

--标识符的作用域与可见性

--标识符的作用域与可见性 测试题

-对象的生存期

--对象的生存期

--对象的生存期 测试题

-类的静态成员

--静态数据成员(例5-4)

--静态函数成员(例5-5)

--类的静态成员 测试题

-类的友元

--类的友元(例5-6)

--类的友元 测试题

-共享数据的保护

--共享数据的保护(例5-7)

--共享数据的保护 测试题

-多文件结构和预编译命令

--多文件结构和预编译命令(例5-10)

--多文件结构和预编译命令 测试题

-第5章小结

--小结

-实验五

--实验五

第6章 数组、指针与字符串(一)

-导学

--导学

-数组的定义与初始化

--数组的定义与使用

--数组的储存与初始化

--一维数组应用举例

--数组的定义与初始化 测试题

-数组作为函数的参数

--数组作为函数参数(例6-2)

--数组作为函数的参数 测试题

-对象数组

--对象数组

--对象数组 测试题

-基于范围的for循环

--基于范围的for循环

-指针的定义和运算

--指针的概念、定义和指针运算

--指针的初始化和赋值

--指针的算术运算、关系运算

--指针的定义和运算 测试题

-综合实例

--综合实例

-实验六(上)

--实验六上

第6章 数组、指针与字符串(二)

-指针与数组

--用指针访问数组元素

--指针数组

--指针与数组 测试题

-指针与函数

--以指针作为函数参数

--指针类型的函数

--指向函数的指针

--指针与函数 测试题

-对象指针

--对象指针

--对象指针 测试题

-动态内存分配

--动态分配与释放内存

--申请和释放动态数组(一)

--申请和释放动态数组(二)

--动态内存分配 测试题

-智能指针

--智能指针

-vector对象

--vector对象

--vector对象 测试题

-对象复制与移动

--深层复制与浅层复制

--移动构造

--对象复制与移动 测试题

-字符串

--C风格字符串

--string类

--字符串 测试题

-第6章小结

--第六章小结

-综合实例

--综合实例

-实验六(下)

--实验六(下)

复制构造函数笔记与讨论

也许你还感兴趣的课程:

© 柠檬大学-慕课导航 课程版权归原始院校所有,
本网站仅通过互联网进行慕课课程索引,不提供在线课程学习和视频,请同学们点击报名到课程提供网站进行学习。