C++远征之封装篇(上) 视频教程 笔记 方便自己查阅和复习,温故而知新。

接着 C++ 封装(1) ——类和对象 继续做笔记。

目录

6 对象的生死离别

6.1 构造函数

代码示例

6.2 默认构造函数

代码示例

6.3 拷贝构造函数

构造函数总结

代码示例

6.4 析构函数

代码示例

总结

参考资料


6 对象的生死离别

对象是如何存储的?

下面举一个例子,定义一个Car类,然后实例化三个对象。

那么这三个对象分别是怎么存储的?如何初始化?

下面使用自己定义的初始化函数( init( ) )来初始化对象。

但是上面的初始化比较繁琐,每次定义一个函数都要调用初始化函数。

有没有一种,只需要初始化一次,并且可以根据条件自动初始化的呢?

这时,C++使用 构造函数 来解决这个问题。

6.1 构造函数

构造函数的规则和特点:

(1) 构造函数在独享实例化时被自动调用;

(2) 构造函数与类同名;

(3) 构造函数没有返回值;

(4) 构造函数可以有多个重载形式;

(5) 实例化对象时仅用到一个构造函数;

(6) 当用户没有定义构造函数时,编译器自动生成一个构造函数。

构造函数有无参构造函数有参构造函数重载构造函数

(1) 无参构造函数 形式见下图:

(2) 有参构造函数 形式见下图:

(3) 重载构造函数 形式见下图:

代码示例

//Teacher.h
#pragma once
#include<iostream>
#include<string>
using namespace std;
class Teacher
{
public:Teacher();//无参构造函数声明Teacher(string name, int age);//有参构造函数声明void setName(string name);string getName();void setAge(int age);int getAge();private:string m_strName;int m_iAge;
};
//Teacher.cpp#include"Teacher.h"
using namespace std;
Teacher::Teacher()
{m_strName = "SB";m_iAge = 3;cout << "Teacher() 无参" << endl;
}
Teacher::Teacher(string name, int age)
{m_strName = name;m_iAge = age;cout << "Teacher(string name, int age) 有参" << endl;
}//函数定义
void Teacher::setName(string name)
{m_strName = name;
}string Teacher::getName()
{return m_strName;
}void Teacher::setAge(int age)
{m_iAge=age;
}int Teacher::getAge()
{return m_iAge;
}
//main.cpp
#include<iostream>
#include<string>
#include"Teacher.h"
using namespace std;int main()
{//调用构造函数Teacher t1;//调用无参构造函数cout << "Name " << t1.getName() <<endl;cout << "Age " << t1.getAge() << endl;cout << "----------------------------------" << endl;Teacher t2("2B",18);//调用有参构造函数cout << "Name " << t2.getName() << endl;cout << "Age " << t2.getAge() << endl;cin.get();return 0;
}

运行结果:

6.2 默认构造函数

在定义构造函数时,可以加入默认值,即默认构造函数, 如下图所示:

还有一种加入默认值的方式为初始化列表,构造函数初始化列表格式如下:

初始化列表特性:

(1) 初始化列表先于构造函数执行;

(2) 初始化列表只能用于构造函数;

(3) 初始化列表可以同时初始化多个数据成员。

那么问题来了,初始化列表有那么重要吗?

下面看一个例子:

如上图所示,初始化列表可以const常量赋值,这个是构造函数无法做到的。

代码示例

要求:

Teacher 类:
自定义有默认参数的构造函数;
使用初始化列表 对数据进行初始化;
数据:名字 年龄;
成员函数:数据成员的封装函数;
拓展:定义可以最多学生的个数,此为常量

//Teacher.h#pragma once#include<iostream>
#include<string>
using namespace std;class Teacher
{
public://构造函数声明  默认构造函数Teacher(string name = "SB", int age = 1, int n = 100);//函数声明void setName(string name);string getName();void setAge(int age);int getAge();int getMax();private:string m_strName;int m_iAge;const int m_iMax;//常量
};
//Teacher.cpp#include"Teacher.h"
using namespace std;
//使用初始化列表
Teacher::Teacher(string name, int age, int m) :m_strName(name), m_iAge(age), m_iMax(m)//常量 必须使用初始化列表
{cout << "Teacher(string name, int age, int m)" << endl;
}//函数定义
void Teacher::setName(string name)
{m_strName = name;
}string Teacher::getName()
{return m_strName;
}void  Teacher::setAge(int age)
{m_iAge = age;
}int  Teacher::getAge()
{return m_iAge;
}int  Teacher::getMax()
{return m_iMax;
}
//main.cpp#include<iostream>
#include<string>
#include"Teacher.h"
using namespace std;/**
Teacher 类:
自定义有默认参数的构造函数
使用初始化列表 对数据进行初始化
数据:名字 年龄
成员函数:数据成员的封装函数
拓展:定义可以最多学生的个数,此为常量
*/int main()
{Teacher t1;cout << t1.getName() << " " << t1.getAge() << " " << t1.getMax() << endl;cout << "-------------------------------------" << endl;Teacher t2("2B", 18, 250);cout << t2.getName() << " " << t2.getAge() <<" "<<t2.getMax()<< endl;cin.get();return 0;
}

运行结果:

6.3 拷贝构造函数

思考:

对于下面的例子,为什么只打印出一行 Student 呢?

实例化对象的时候一定会调用构造函数吗?

原因是在复制对象时,C++会自动生成拷贝构造函数。

拷贝构造函数 形式如下:

拷贝构造函数特性:

(1) 如果没有自定义的拷贝构造函数时,则系统会自动生成一个默认的拷贝构造函数。

(2) 当采用直接初始化或复制初始化实例化对象时,系统会自动调用拷贝构造函数。

构造函数总结

代码示例

要求:

定义 Teacher 类:自定义拷贝函数
数据成员:名字  年龄
成员函数:数据成员的封装函数

//Teacher.h#pragma once#include<iostream>
#include<string>
using namespace std;class Teacher
{
public://构造函数声明  Teacher(string name = "SB", int age = 1);Teacher(const Teacher &tea);//拷贝构造函数声明//函数声明void setName(string name);string getName();void setAge(int age);int getAge();int getMax();private:string m_strName;int m_iAge;
};
//Teacher.cpp#include"Teacher.h"
using namespace std;
//使用初始化列表
Teacher::Teacher(string name, int age) :m_strName(name), m_iAge(age)
{cout << "Teacher(string name, int age)" << endl;
}//拷贝构造函数定义
Teacher::Teacher(const Teacher &tea)
{cout << "Teacher(const Teacher &tea) 拷贝" << endl;
}//函数定义
void Teacher::setName(string name)
{m_strName = name;
}string Teacher::getName()
{return m_strName;
}void  Teacher::setAge(int age)
{m_iAge = age;
}int  Teacher::getAge()
{return m_iAge;
}
//main.cpp#include<iostream>
#include"Teacher.h"using namespace std;void test(Teacher t)
{}int main(){Teacher t1;Teacher t2 = t1;Teacher t3(t1);cout << "------------------------------------" << endl;test(t1);cin.get();return 0;}

运行结果:

6.4 析构函数

析构函数不允许添加任何参数,不能重载。

思考:析构函数有存在的必要性吗?

析构函数特性:

(1) 如果没有自定义的析构函数,则系统自动生成;

(2) 析构函数在对象销毁时自动调用;

(3) 析构函数没有返回值,没有参数也不能重载。

代码示例

要求:

Teacher 类:
1 自定义拷贝函数 和析构函数
2 普通方式实例化对象,在销毁时是否自动调用析构函数? 是
3 通过拷贝函数实例化对象,在销毁对象时是否自动调用析构函数? 是
数据成员:名字  年龄
成员函数:数据成员的封装函数

//Teacher.h#pragma once#include<iostream>
#include<string>
using namespace std;class Teacher
{
public://构造函数声明  Teacher(string name = "SB", int age = 1);Teacher(const Teacher &tea);//拷贝构造函数声明~Teacher();//析构函数 声明//函数声明void setName(string name);string getName();void setAge(int age);int getAge();int getMax();private:string m_strName;int m_iAge;
};
//Teacher.cpp#include"Teacher.h"
using namespace std;
//使用初始化列表
Teacher::Teacher(string name, int age) :m_strName(name), m_iAge(age)
{cout << "Teacher(string name, int age)" << endl;
}//拷贝构造函数定义
Teacher::Teacher(const Teacher &tea)
{cout << "Teacher(const Teacher &tea) 拷贝" << endl;
}//析构函数 定义
Teacher::~Teacher()
{cout<<"~Teacher() 析构"<<endl;
}//函数定义
void Teacher::setName(string name)
{m_strName = name;
}string Teacher::getName()
{return m_strName;
}void  Teacher::setAge(int age)
{m_iAge = age;
}int  Teacher::getAge()
{return m_iAge;
}
//main.cpp#include<iostream>
#include<string>
#include"Teacher.h"
using namespace std;/**
Teacher 类:
1 自定义拷贝函数 和析构函数
2 普通方式实例化对象,在销毁时是否自动调用析构函数? 是
3 通过拷贝函数实例化对象,在销毁对象时是否自动调用析构函数? 是
数据成员:名字  年龄
成员函数:数据成员的封装函数
*/void test(Teacher t)
{}int main()
{Teacher t1;cout << "----------------------------------" << endl;Teacher *p = new Teacher;delete p;cout<<"----------------------------------"<<endl;Teacher t2(t1);// 值传递 调用 会触发拷贝构造函数cin.get();return 0;
}

运行结果:

总结

数据成员成员函数 组成。


参考资料

[1]  C++远征之封装篇(上) (注:图片均来自视频中PPT)

C++ 封装(2): 构造函数和析构函数相关推荐

  1. C++封装、构造函数、析构函数

    封装.构造函数.析构函数 1 封装 构造函数 对象初始化 构造函数的基本语法 构造函数的初始化列表 构造函数的重载 默认构造函数 析构函数 对象的销毁 析构函数的基本概念 析构函数的语法 1 封装 ① ...

  2. 【黑马程序员 C++教程从0到1入门编程】【笔记4】C++核心编程(类和对象——封装、权限、对象的初始化和清理、构造函数、析构函数、深拷贝、浅拷贝、初始化列表、友元friend、运算符重载)

    黑马程序员C++教程 文章目录 4 类和对象(类属性[成员属性],类函数[成员函数]) 4.1 封装 4.1.1 封装的意义(三种权限:public公共.protected保护.private私有)( ...

  3. 【C++碎碎念】面向对象(封装与访问控制、构造函数与析构函数、拷贝函数)

    目录 一.封装与访问控制 二.构造函数与析构函数 三. 拷贝构造函数 一.封装与访问控制 1.封装的优势: 1)隐藏实现细节,提供公共的访问方式: 2)提高了代码的复用性: 3)提高了安全性. 2.分 ...

  4. C++构造函数与析构函数

    几乎所有的面向对象的编程语言都保护构造函数与析构函数,好学者就要举手了,啥情况啊,Java里面不就没有析构函数嘛.好吧,你问倒我了,不过可以认为Java的垃圾自动回收机制实现了对象析构的功能.管他呢, ...

  5. C++文件头,命名空间,new和delete,内联函数,引用,函数重载,构造函数和析构函数,深拷贝和浅拷贝,explict,this指针

     目 录 1      开始学习C++............................................................................... ...

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

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

  7. C++入门:构造函数,析构函数,拷贝构造函数,运算符重载详解

    目录 类的6个默认成员函数 一.构造函数 1.概念 2.特征如下: (1) 函数名与类名相同. (2)无返回值. (3)对象实例化时编译器自动调用对应的构造函数. (4)构造函数可以重载. (5)如果 ...

  8. 【C++学习笔记2】构造函数、析构函数、函数多态、抽象类、函数模板

    这次笔记介绍构造函数.析构函数.函数多态.抽象类.函数模板 一.构造函数 1.在定义对象,构造函数程序将自动执行,他的类型跟类名一致 函数声明最好放在自己的类里面,这样才符合类的封装,也可以像下面一样 ...

  9. C++:构造函数,析构函数及友元函数

    我们先从一个题来开始:这是改正之后的样子. #include <iostream> using namespace std; class MyClass { public:MyClass( ...

最新文章

  1. Nature:揭示大脑中的免疫记忆
  2. ubuntu-18.04 root登录图形界面失败问题解决方案
  3. 全球与中国InGaAs光电二极管传感器市场投资机会与市场风险评估报告2022-2028年
  4. CSP2021NOIP2021游记
  5. 前端学习(2828):数组和对象循环
  6. Modbus协议栈开发笔记之八:Modbus ASCII Master开发
  7. java 获取本机ip_linux获取本机IP
  8. 设计模式---面向对象设计原则之单一职责原则
  9. jQuery特效:实现简易轮播图
  10. Tip: Unicode Debug和Debug有什么区别?
  11. 机器学习会成为2017年大数据​分析的瓦解者吗?
  12. linux系统上查询ip地址归属
  13. eclipse安装STS插件失败解决办法
  14. java毕业设计大学生体检管理系统Mybatis+系统+数据库+调试部署
  15. GmSSL 国密MS2/SM3/SM4/SM9/ZUC/SSL密码工具箱
  16. 如何用计算机计算一组数据的方差,Excel计算一组数据的方差的操作方法
  17. STM32显示图片,将图片转换为十六进制数组便捷工具
  18. unity3D中导出webgl并使用js进行交互
  19. 用于拆解和组合PDF中各个对象的shell脚本
  20. 让机房温度可视化:物联网下的数据中心环境运维新方式

热门文章

  1. html css3风车,【干货!】如何利用CSS3新属性创建一个风车动画
  2. html手机端禁止放大缩小
  3. ThinkPHP官网头像上传原理
  4. virtualenv简介
  5. vivo恢复出厂设置后云服务器,vivo 手机恢复出厂设置后不能开机,怎么办,一招就可解决!...
  6. 百度搜索开始屏蔽部分网赚行业关键词!
  7. php ms2,php-python2-python3跨语言rsa公钥加密私钥解密
  8. python输入4个数字_Python中输入任意四个数,输出他们由大到小排序
  9. 兄弟们,网络安全培训机构现在哪个好?
  10. 创业step one