c++封装:
封装:封装可以达到对外提供接口,屏蔽数据,对内开发数据
C语言中的封装:当单一变量无法完成描述需求的时候,结构体类型解决了这一问题。
C++的封装:class 封装的本质,在于将数据和行为,绑定在一起然后通过对象来完成操作。
类与对象
类的声明:类是一种用户自定义类型
class 类名称
{
public:
公有成员(外部接口)
私有成员
保护成员
};
权限修饰符:public、private(set/get)、protected
面向对象编程实例:栈的实现,单向链表的实现
为什么需要构造函数?
构造函数是特殊的成员函数
创建类类型的新对象,系统自动会调用构造函数
构造函数是为了保证对象的每个数据成员都被正确初始化
构造函数的定义及特点:
函数名和类名完全相同
不能定义构造函数的返回类型,也不能使用void
通常情况下构造函数硬声明为公有函数
构造函数被声明为私有有特殊用途
构造函数可以有任意类型和任意个数的参数,一个类可以有多个构造函数(重载)
构造函数的种类:
默认构造函数(无参构造函数)----default、delete
有参无参的构造函数
this指针
构造函数初始化列表
const成员的初始化只能在构造函数初始化列表中进行
引用成员的初始化也只能在构造函数初始化列表中进行
对象成员(对象所对应的类没有默认构造函数)的初始化,也只能在构造函数初始化列表中进行
拷贝构造函数
功能:使用一个已经存在的对象来初始化一个新的同一类型的对象
声明:只有一个参数并且参数为该类对象的引用
Test:Test(const Test& other):num_(other.num_) { cout<<“initializing with other”<<num_<<endl; }
拷贝赋值运算符
Test& Test::operator=(const Test& other) { cout<<“Test::operator=”<<endl; if(this==&other) return *this; num_=other.num_; return *this; }
深拷贝与浅拷贝
=运算符必须实现深拷贝
对于独一无二的对象禁止拷贝,将拷贝构造函数私有化
类型转换构造函数
单个参数的构造函数
将其他类型转换为类类型
例子:
Test::Test(int num) { num_=num; cout<<"initializing "<<num_<<endl; }
隐式转换和explicit:Timer t = 12;(隐式类型转换)
explicit:不能隐式转换,只能显示转换
类型转换运算符重载:
必须是成员函数,不能是友元函数
没有参数
不能指定返回类型
函数原型:operator 类型名();
移动构造函数
拷贝是最消耗资源和降低效率的;尤其是临时对象、容器类
对象移动:A移动到B,A就不能再使用;
移动并不是内存的数据移动到其他内存,而是变更所有权;
变更所有权并不是变更所有属性的所有权
引入右值引用的目的:提高程序运行效率、把拷贝对象变成移动对象,省去调
用拷贝构造函数,拷贝赋值构造函数,省去开辟空间过程;
std::move:本身并不移动对象,只是将对象的类型转换为右值
使用注意事项:调用此函数即保证后面不会再使用传入的对象
移动拷贝构造函数:Person(const Person&& person)
移动赋值运算符:Person& operator=(Person&& person)
移动构造函数及移动赋值运算符实例:
使用注意事项:1)移动后源对象必须是有效的,可析构的
2)一个类定义了自己的拷贝构造函数,拷贝赋值运算符或析构
函数,编译器就不会为它合成移动构造函数和移动赋值运算符。
3)定义了一个移动构造函数或移动赋值运算符的类必须也定义
自己的拷贝构造函数和拷贝赋值运算符,否则拷贝构造函数和拷
贝赋值运算符会被定义为删除的
4)使用=default显式要求编译器生成合成的移动操作,且编译器
不能移动所有成员
5)移动构造函数和移动赋值运算符必须标记为noexcept
析构函数
定义:1)C++中的类可以定义一个特殊的成员函数清理对象,这个特殊的成员函数叫做
析构函数
语法:~ClassName()
2)析构函数没有参数也没有任何返回类型的声明
3)析构函数在对象销毁时自动被调用
防止内存空间泄露
运算符重载
成员函数、属性
对私有属性添加set/get方法
类内初始化
static关键字
static成员
static成员需要在类定义体外进行初始化与定义
static成员的优点:
static成员的名字是在类的作用域中,可以避免与其他类成员冲突
可以实施封装,static成员可以是私有的,而全局对象不可以
static const 成员的使用:
整型static const成员可以在类定义体中初始化,该成员可以不在类
体外进行定义
static成员函数
const关键字
const成员函数
const成员函数不会修改对象的状态
const成员函数只能访问数据成员的值,而泵修改她
mutable关键字
用mutable修饰的数据即使在const对象或在const成员函数中都可以被修改
空类默认生成的成员
class Empty{};
Empty(); //默认构造函数
Empty(const Empty&); //默认拷贝构造函数
~Empty(); //默认析构函数
Empty&operator=(const Empty&); //默认赋值运算符
Empty* operator&(); //取值运算符
const Empty* operator&()const; //取值运算符const
浅谈对象模型-对象大小
指向类成员的指针
指向类数据成员(属性)的指针
定义:<数据类型><类名>::<指针名>
赋值初始化:<数据类型><类名>::<指针名> = &<类名>::<非静态数据成员>
注意事项:
指向非静态数据成员的指针在定义时必须和类相关联,在使用时必须和具体的对象
关联
由于类不是运行时存在的对象。因此,在使用这类指针时,需要首先指定类的一个
对象,然后,通过对象来引用指针所指向的成员。
指向类成员函数的指针
定义:<数据类型>(<类名>::<指针名>)(<参数列表>)
赋值初始化:<数据类型>(<类名>::<指针名>)(<参数列表>) = &<类名>::<非静态成
员函数>
使用注意事项:同上
总结:
指向类的成员属性的指针与普通意义上的指针不一样。存放的是偏移量。
用指向类员函数的指针,实现更加隐蔽的接口。
练习:自定义实现string类
http://note.youdao.com/noteshare?
id=5117142c83fb2c4bd61b2f90d1fc4288&sub=9D530165D0024EE79049D3E65BE92EE
D
运算符重载:
1.友元机制
友元是一种允许非类成员函数访问类的非公有成员的一种机制。
可以把一个函数指定为类的友元,也可以把整个类指定为另一个类的友元。
友元函数
友元函数在类作用域外定义,但他需要在类体中进行说明
friend 类型 友元函数名(参数表);
注意事项
友元函数不是类的成员函数,在函数体中访问对象的成员必须用对象加运算符“.”加对象成员名。但友元函数可以访问类中的所有成员。
友元函数破坏了面向对象程序射设计类的封装性,所以尽可能少使用。
友元的作用在于提高程序的运行效率(即减少了类型和安全性检查及调用的时间开销)
友元成员函数
友元类
注意事项:
友元关系是单向的
友元关系不能被传递
友元关系不能被继承
2.运算符重载(一)
运算符重载介绍
运算符重载允许把标准运算符(如+、—、、/、<、>等)应用于自定义数据类型的对象
运算符重载的作用
直观自然,可以提高程序的可读性
体现了C++的可扩充性
运算符重载,本质上是函数重载
运算符重载仅仅只是语法上的方便,它是另一种函数调用的方式
运算符重载的注意事项
不要滥用重载、因为它只是语法上的方便,所以只有在涉及的代码更容易写、尤其是更易读时才有必要重载
运算符重载的实现
成员函数重载
成员函数原型格式: 函数类型 operator 运算符(参数表);
成员函数定义的格式:函数类型 类名::operator 运算符(参数表){函数体;}
友元函数重载
友元函数原型格式:friend 函数类型 operator 运算符(参数表);
友元函数定义的格式:friend 函数类型 类名::operator 运算符(参数表){函数
体;}
运算符重载规则
运算符重载不允许发明新的运算符
不能改变运算符操作对象的个数
运算符被重载后,其优先级和结合性不会改变
不能重载的运算符(:: ?: . . sizeof)
成员函数重载和友元函数重载的选择:
1.一般情况下,单目运算符最好重载为类的成员函数;双目运算符则最好重载为类的友元函数。
2.以下一些双目运算符不能重载为类的友元函数:=、()、[]、->。
3.类型转换运算符只能以成员函数方式重载
4.流运算符只能以友元的方式重载
3.运算符重载(二)
++运算符重载
实例:Integer类(友元和成员函数重载方式)
先自加后使用
先使用后自加
!运算符重载
实例:String类(成员函数重载方式)
赋值运算符重载
实例:String类(成员函数重载)
String& operator=(const String& other);
String& operator=(const char* str);
4.运算符重载(三)-String类的实现
[ ]运算符重载
char& operator[](unsigned int index);
const char& operator[](unsigned int index) const;
+运算符重载
friend String operator+(const String& s1, const String& s2);
+=运算符重载
String& operator+=(const String& other);
流运算符重载
friend ostream& operator<<(ostream& os, const String& str);
friend istream& operator>>(istream& is, String& str);
5.运算符重载(四)
类型运算符重载
类型转换运算符重载
operator int();