复习笔记(二)——C++面向对象设计和使用
面向对象编程(OOP)
面向对象(Object Oriented )是认识事务的一种方法,是一种以对象为中心的思维方式
面向对象的程序设计:
对象=(算法+数据结构)
程序=对象+对象+……+对象
面向对象程序设计模拟自然界认识和处理事物的方法,将数据和对数据的操作方法放在一起,形成一个相对独立的整体——对象(object),同类对象还可抽象出共性,形成类(class )。一个类中的数据通常只能通过本类提供的方法进行处理,这些方法成为该类与外部的接口。对象之间通过消息(message)进行通讯。
我们把对象之间产生相互作用所传递的信息称做消息。
C++将“向对象发消息”处理成“调用对象的某个成员函数”
基本概念——对象
世界上所有的事物都可以称为对象(Object)。对象可以是有形的如:一台电视机等。也可以是无形的如:帐户、一项记录等。
一个对象就是一个独立存在的客观事物,它由一组属性和对属性进行操作的一组操作构成。
- 属性是对象静态特征的描述
- 操作是对象动态特征的描述
属性和操作是对象的两大要素。如电视的属性有:品牌、尺寸、重量等。操作有:收视、选台、音量调节等。
基本概念——类
类是一个抽象的概念,用来描述某一类对象所共有的、本质的属性和类行为。
类实根据抽象的原则对客观事物进行归纳和划分。
面向对象的基本特征
- 抽象
- 封装和数据隐藏(简单介绍)
- 继承
- 多态
封装和数据隐藏
封装是指按照信息屏蔽的原则,把对象的属性和操作结合在一起,构成一个独立的对象。
通过限制对属性和操作的访问权限,可以将属性“隐藏”在对象内部,对外提供一定的接口,在对象之外只能通过接口对对象进行操作。
封装性增加了对象的独立性,从而保证了数据的可靠性。
外部对象不能直接操作对象的属性,只能使用对象提供的服务。
抽象的设计思路
数据抽象化为属性
处理过程抽象化为操作(方法)
-例如:当建立一个图书管理系统时,通过直觉知道系统里一定要有图书管理员/读者/书这些对象, 而其中读者的行为含有借书/还书,学生还有其相应的学号/姓名/班级等内容
类的定义
C++通过建立数据类型——类来支持封装和数据隐藏。一个定义完好的类可以作为独立模块使用。
类的定义格式分为说明部分和实现部分
—说明部分包含数据成员和成员函数说明
—实现部分是用来对成员函数的定义
类的一般定义格式如下:
class <类名>
{public :<公有数据成员和成员函数>;protected:<保护数据成员和成员函数>;private :<私有数据成员和成员函数>;
};
class
是定义类的关键字是数据类型说明符,<类名>是一个标识符,用于唯一地标识一个类(新的数据类型),类名后面花括号扩起来的部分是类体(Class Body)。
类体中定义了类成员表(Class Member List)
—数据成员(Data Member)
—函数(Member Function)
public、protected和private是访问限定符(access specifier)
一般在类体内先说明公有成员,它们是用户所关心的,后说明私有成员,它们是用户不感兴趣的,但此顺序并不是必须的。
***注意:
①在类的说明部分之后必须加分号“;”。
②类的定义放在一个头文件中(.h),供其它需要使用该类的文件包含
③类的实现部分放在一个源文件中(.cpp),该文件需要包含定义类的头文件
④类的定义和实现可以放在一个文件里,但不提倡,因为结构不清晰,影响了程序的可读性
数据成员(属性)
类中的数据成员的类型可以是任意的,可以定义各种类型的变量、指针、数组等,甚至是其他类的对象。
在说明数据成员时,一般按数据成员的类型大小,由小到大说明,这样可提高空间利用率。
在类的定义中只能声明数据成员,不允许对所定义的数据成员进行初始化。
类的数据成员只能在类里声明,类的数据成员最好都是私有的
外部函数需要修改它,一般也只给它提供公有函数接口,让它通过类的公有成员函数访问类的私有数据数据成员也可以放在public部分,但不提倡
成员函数(方法)
成员函数可以直接使用类定义中的任一成员,可以处理数据成员,也可调用成员函数。
类的成员函数定义通常可采取两种方式,即外部定义和内部定义(不推荐!影响到了程序的可读性)。
成员函数的实现一般放在类的外面,在类里面对函数的原型进行声明
成员函数的实现在类的定义外面时,必须声明其所属,在函数名前加类名和作用域运算符“::”,用来表示某个成员函数属于哪个类的,定义格式如下:
返回类型 类名::成员函数名(参数说明)
{函数体
}
类成员函数的实现也可以放在类里,不需要加类名和作用域运算符
访问控制
三个访问说明符:public、private和protected
作用:控制对类的成员的访问
在用class定义的类中,默认的访问方式是private
在类的定义中,三个访问说明符都可以使用多次(不提倡)。它们的作用域是从该说明符出现开始到下一个说明符之前或类体结束之前结束。
访问符说明
private:类的私有成员只能被类的成员函数、友元函数、友元类访问,类外无法访问他们
protected:类的受保护成员能被类的成员函数、友元函数、友元类和派生类成员函数访问
public:类的公有成员可以被类的成员函数、友元函数、友元类所有能访问到类的对象的外部程序代码直接访问,这部分往往是一些操作(即成员函数)
类的公有成员是类的对外接口
类的功能
类定义了函数(方法)和数据(属性)的访问控制属性
—哪些成员可被外界直接访问
—哪些成员只能被自己的成员函数访问
封装和信息隐藏技术使类变得很安全
私有数据成员只有类自己的成员函数能访问
只要确保成员函数操作的合理合法性,对象就是安全的
提高了程序的可维护性
对象的定义
对象是类的实例。对象是属于某个已知的类。
定义对象之前,一定要先定义好该对象的类。
定义好的类可以作为新的数据类型来使用
声明的语法:类的名称 对象的名称;
例如:
例如:
Stack oneStack; //Stack类型的对象
Stack arrayOfStack[10]; //Stack类型的对象数组
Stack *pStack=&oneStack; //Stack类型的指针
Stack &s = oneStack; // 引用一个Stack对象
构造函数
对于对象的初始化,采用构造函数(constructor)。编写一个或一组构造函数。构造函数是特殊的成员函数
构造函数的功能:为对象分配空间;对数据成员赋初值;请求其他资源。
如何声明构造函数:
—函数名和类名完全相同
—不能定义构造函数的类型(返回类型),也不能使用void
—构造函数应声明为公有函数,但它不能像其他成员函数那样被显式地调用
—构造函数可以有任意类型和任意个数的参数,一个类可以有多个构造函数(重载)
创建类的对象时,自动调用类的构造函数
创建一个对象时只调用一个构造函数(根据参数列表)且只在创建时调用一次
构造函数的种类
普通构造函数:有两个或两个以上参数的构造函数
默认构造函数
复制(拷贝)构造函数
类型转换构造函数
重载构造函数
在一个类需要接受不同的初始化值时,就需要编写多个构造函数, 他们之间构成重载关系。
示例:
class Student{private:char m_No[4],m_Name[21];int m_Age,m_Score[5];
public:Student(); //默认构造函数Student(char *name,int age,int score[5]); //重载构造函数
};
默认构造函数
哪种构造函数是默认构造函数?
没有参数或者所有的参数都有默认值的构造函数。
类里一定会有默认构造函数吗?
如果类中没有声明构造函数,编译器将自动产生一个公共的默认无参数构造函数;如果存在一个构造函数声明,那么编译器不会产生一个默认的构造函数
默认构造函数何时调用?
没有指明初始化对象时,便按默认构造函数来初始化该对象。
例如:Person p1,p2; //使用默认构造函数对p1和p2进行初始化一个类中只能有一个默认构造函数
(如果一个构造函数的所有参数均有默认值,这时再定义无参数的默认构造函数无意义,会产生调用时二义性)
构造函数中使用默认参数
可以为类的成员函数指定参数的默认值,包括构造函数在内。
要把默认参数值放在函数声明中,而不应放在函数定义中
如果一个构造函数的所有参数均有默认值,这时再定义无参数的默认构造函数无意义,将产生调用时二义性。
示例:
class CCube{public:CCube(double len);CCube(int len=12);//CCube();
private:double m_len;
};
CCube::CCube(int len){m_len=len;}
拷贝(复制)构造函数
特殊的构造函数
功能:使用一个已经存在的对象来初始化一个新的本类的对象
声明:只有一个参数并且参数为该类对象的引用
class 类名{public: 类名(类名 &对象名);};
如果类中没有说明复制构造函数,则系统自动生成一个缺省复制构造函数,作为该类的公有成员。
浅复制和深复制
浅复制:将对象数据成员的值进行简单的复制
深复制:不仅将对象数据成员的值进行复制,而且对指针型数据成员生成新空间,然后复制对应的值
实例:
#include <string.h>
#include <iostream.h>
class Employee
{public:Employee(char *n);Employee(Employee &emp);~Employee();
public:char *name;
};
Employee::~Employee()
{//析构函数delete [] name;
}
Employee::Employee(char *n)
{name = new char[strlen(n)+1];strcpy(name,n);
}
Employee::Employee(Employee &emp)
{int len=strlen(emp.name);name=new char[len+1];strcpy(name,emp.name);
}
int main()
{Employee emp1("zhang");Employee emp2(emp1);//Employee emp2=emp1;cout<<"emp2.name = "<<emp2.name<<endl;return 0;
}
**注意:对象中包含动态分配的数据成员时,复制构造函数的实现不能只是简单的赋值。应该先为当前对象的数据成员分配新的空间,再将参数对象中相应的数据复制过来。
拷贝构造函数的其他作用
当函数的形参是类的对象,调用函数时,进行形参与实参结合时使用。这时要在内存新建立一个局部对象,并把实参拷贝到新的对象中。理所当然也调用拷贝构造函数。
当函数的返回值是类对象,函数执行完成返回调用者时使用。理由也是要建立一个临时对象中,再返回调用者。为什么不直接用要返回的局部对象呢?因为局部对象在离开建立它的函数时就消亡了,不可能在返回调用函数后继续生存,所以在处理这种情况时,编译系统会在调用函数的表达式中创建一个无名临时对象,该临时对象的生存周期只在函数调用处的表达式中。所谓return 对象,实际上是调用拷贝构造函数把该对象的值拷入临时对象。如果返回的是变量,处理过程类似,只是不调用构造函数。
转换构造函数
提供了单个参数的构造函数
相当于将一个其他类型的数值或变量转换为自身类型的数据。
类的构造函数只有一个参数是非常危险的,因为编译器可以使用这种构造函数把参数的类型隐式转换为类类型
实例:
#include <string.h>
#include <iostream.h>
class CCube
{public:CCube(double len){m_len=len;}
public:double m_len;
};
int main()
{CCube cube=12.4;cube=11; //隐式转换cout<<"cube.m_len = "<<cube.m_len<<endl;return 0;
}执行结果:
cube.m_len = 11
explicit关键字
只提供给类的构造函数使用的关键字。
编译器不会把声明为explicit的构造函数用于隐式转换,它只能在程序代码中显示创建对象
#include <string.h>
#include <iostream.h>
class CCube
{public:explicit CCube(double len){m_len=len;}
private:double m_len;
};
int main()
{CCube cube = 12.4;//不允许//cube=11;//不允许return 0;
}
析构函数
特殊的成员函数
作用:撤销对象前做清理工作,一般是释放对象在生存期间动态申请的空间
当对象超出其定义范围时(即释放该对象时),编译器自动调用析构函数。
-对象被定义在函数体内,则当这个函数结束时,该对象的析构函数被自动调用。
-对象是使用new运算符动态创建的,在使用delete运算符释放它时,delete将会自动调用析构函数
函数名和类名相似(前面多了一个字符“~”)
注意:析构函数没有返回类型,没有参数,析构函数不能被重载
如果没有定义析构函数,编译器会自动生成一个默认析构函数,其格式如下:
类名::~默认析构函数名( )
{}
默认析构函数是一个空函数。
示例:
class Student
{public:Student();~Student();
private:char *m_name;
};
Student :: Student()
{cout<<"Default constructor called"<<endl;m_name=new char[5];strcpy(m_name,"abc");
}
Student ::~Student()
{cout<<"Free"<<endl;delete []char;
}
复习笔记(二)——C++面向对象设计和使用相关推荐
- PHP学习笔记二: 面向对象设计
public 表示全局,类内部外部子类都可以访问: 1 <?php 2 3 class Test{ 4 public $name='Janking', 5 $sex='male', 6 $age ...
- c++语言自定义操作符,C++语言复习笔记二
C++语言复习笔记二 零.OOP 特征:抽象-封装-继承-多态 一.自定义数据类型 1.类 class 类名 { private: 私有成员(本类) public: 公共成员(所有) protecte ...
- python基础笔记二_面向对象
面向对象 Object Oriented 概述 面向过程 1.分析出解决问题的步骤,然后逐步实现.例如:婚礼筹办-- 发请柬(选照片.措词.制作)-- 宴席(场地.找厨师.准备桌椅餐具.计划菜品.购买 ...
- 那年学过的Java笔记二SE面向对象
面向对象 面向对象编程 1 什么是对象? 万物皆对象. 2 什么是面向对象? 面向对象就是指以特征/属性和行为的观点去分析现实世界中事物的方式.3 什么是面向对象编程? 面向对象编程就是指先以面向对象 ...
- 概率论复习笔记二——离散型分布和连续型分布
一.离散型分布 1.1 伯努利分布 在一次试验中,事件AAA出现的概率为ppp,不出现的概率为q=1−pq=1-pq=1−p,若以β\betaβ记事件AAA出现的次数,则β\betaβ取0,10, 1 ...
- 电子商务复习笔记二:电子商务相关知识与技术
万维网 万维网概述 万维网(亦作"网络"."WWW"."3W",英文"Web"或"World Wide Web ...
- 操作系统复习笔记(二)
1.问答题:有一个文件F,有A,B两组进程共享这个文件,同组的进程可以同时读文件F,但当有A组(或B组)的进程在读文件F时就不允许B组(或A组)的进程读, 解:定义两个计数器C1,C2,分别记录A组和 ...
- 《设计模式:可复用面向对象软件的基础》——面向对象设计原则、创建型模式(笔记)
文章目录 二.面向对象设计原则(补充) 2.1 重新认识面向对象 2.2 面向对象设计原则 2.2.1 依赖倒置原则(DIP) 2.2.2 开放封闭原则(OCP) 2.2.3 单一职责原则(SRP) ...
- java面试笔记二:java的面向对象
java面试笔记二:面向对象 面向对象和面向过程的区别 过程就是函数,就是写方法,就是方法的一种实现. 对象就是将函数,属性的一种封装.用人们思考习惯的方式思考问题. 匿名对象 即:创建对象时没有指定 ...
- 《微型计算机原理与接口技术》复习笔记(二)
使用教材为 <微型计算机原理与接口技术>(慕课版) 孙丽娟.李爱群.陈燕俐.周宁宁.邓玉龙编著 默认存储器单元的地址编排顺序从上往下,地址从低向高编排 微机原理复习笔记一 微机原理复习笔记 ...
最新文章
- Spring bean 的生命周期
- Python的安装 || python介绍
- qpython3l手机版怎么用_qpython怎么用
- JavaScript中数组使用总结
- Disjoint Set
- Strange Partition CodeForces - 1471A
- 百度面试题:从输入url到显示网页,后台发生了什么?
- Pandas快速上手(一):基本操作
- 诗与远方:无题(三十八)
- 提取图像色彩主色调工具
- 如何给一个文件重命名?
- AcWing 4242. 货币兑换(SPFA or Bellman 判正权环)
- springboot整合mybatis源码分析
- java:html转pdf的方法
- 恶意代码分析实战Lab3-1
- MEGA使用VCF/Hapmap数据构建进化树
- 安卓查看内存读写测试软件_办公电脑太慢?试试加条内存就好!内存晒单和内存问题科普...
- 【LeetCode/力扣】1723. 完成所有工作的最短时间
- pip install pygame_Python、PyGame游戏项目
- 9. Data Manipulation with dplyr in R
热门文章
- hibernate savealiasentity 保存后id为空_好程序员Java教程分享Java面试题之Hibernate
- 59. Leetcode 81. 搜索旋转排序数组 II(二分查找-局部有序)
- Leetcode 剑指 Offer 13. 机器人的运动范围 (每日一题 20210906)
- Batch Normalization的细致理解
- 深度学习核心技术精讲100篇(六十四)-特征选择原理及应用实战案例
- 深度学习100例 | 第29天-ResNet50模型:船型识别
- tushare股票数据接口
- 列数较多的csv文件导入mysql数据库(过程及问题记录)
- 微信QQ聊天记录分析工具-微Q
- 提高开源项目逼格-为你的github项目添加Travis CI