类和对象
构造函数
- 有了自定义构造函数,就不会存在默认构造函数了
复制构造函数
X::X(const X & a);
//如果没有& 则调用复制构造函数时候仍需要调用构造函数(因为a未构造),还可以减少一次内存拷贝,
X c1;//调用无参构造函数
X c2(c1);//调用
X c2=c1;
fun(c1);
//都是在构造对象时,与“=”运算符重载不同
- 默认复制构造函数可完成 复制功能(保护成员无效)
- 可有多个形参,但必须带默认值
- 需要用到深拷贝!
类型转换构造函数
只含一个参数,实现类型的自动转换
c1 = 9 //9会利用类型构造函数创建临时对象 再复制
A a(9);
A a=9 ;
析构函数
调用位置
- 函数对象参数消亡
- 对象作为返回值 的创建临时对象语句结束后消亡
obj = fun(obj);
- 全局对象消亡
多态
虚析构函数
引入:删除指向派生类的 基类指针 时,并不会调用派生类的析构函数
用法 :
- 只要基类定义为虚函数 则派生类的析构函数都默认为虚函数;
- 如果基类存在虚函数,则析构函数也该为虚函数
纯虚函数
virtual void fun()=0;
引入:
- 为了方便使用多态特性,我们常常需要在基类中定义虚拟函数。
- 在很多情况下,基类本身生成对象是不合情理的。例如,动物作为一个基类可以派生出老虎但动物本身生成对象明显不合常理。
用法:
- 抽象类的成员函数可以调用纯虚函数(调用的是派生类的),但是析构函数和构造函数不可以(编译出错,此时派生类对象已经被删除/未构造)
- 派生类中要实现所有纯虚函数,才能成为非抽象类
- 创建抽象类对象会报错
运算符重载
基本运算符
//(返回值)
X:operator+(const X & a,const X & b);
//a+b = operator+(a,b);
X: operator+(const X & a)
//a-b =a.operator-(b);成员函数少1参数
赋值运算符“=”
X& operator = (const X &ex);
if(this == &s)return *this;
delete[];
str=new .
strcpy();
return *this;
注意:
- 只能重载为成员函数
- 返回对象的引用&,可连等
- 不能用在初始化
- 与拷贝构造函数区分
深拷贝:
- 默认是浅拷贝,常在遇到动态成员会出错
- 原空间指针丢失
- 会重复delete同一片区
-
重载为友元函数
引入
- 重载为成员函数不能满足需求,重载为普通函数,又不能访问私有成员,引入友元
a=a+5; a.op+5
a=5+a; 5.op+a //wrong需要重载为普通函数,总共需要2个 operator+函数
可变长数组类的实现
memcpy(ptr,a.ptr,sizeof(int)*a.size)
X &OPERATOR = (const X &a);//需要深拷贝
~X()delete
(类型) & OPERATOR[](int i);
//返回值要能满足a[i]=4,n=a[i]