【c++基础】9.类和对象——类的实现2

4.拷贝构造函数

深拷贝与浅拷贝
当类的数据成员中没有指针时,使用浅拷贝完全没有问题,但如果有,使用浅拷贝时,只会将该指针拷贝出去,而不会另外开辟空间,即两个对象使用了同一块空间,这就很扯淡了。深拷贝就是在需要复制的地方重新开辟空间。
如果没有显式写出编译器会自动加上一个默认的,但是浅拷贝,因此如果数据成员有指针的话需要自定义拷贝构造函数。
调用拷贝构造函数的三种情况:
函数以传值方式传递对象、函数以传值方式返回对象、一个对象用另一个对象对进行初始化(如CLASSNAME CLASS1=CLASS2)。
析构函数
在对象销毁前调用,释放在对象中通过new等方式开辟的内存空间(new可以参考内存机制),防止内存泄露。
1) 如果在一个函数中定义了一个对象(auto 局部变量),当这个函数运行结束时,对象就会被销毁,在对象被销毁前自动执行析构函数。
2) static 局部对象在函数调用结束时并不销毁,因此也不调用析构函数,只有在程序结束时(如 main 函数结束或调用 exit 函数)才调用 static 局部对象的析构函数。
3) 如果定义了一个全局对象,也只有在程序结束时才会调用该全局对象的析构函数。
4) 如果用 new 运算符动态地建立了一个对象,当用 delete 运算符释放该对象时,先调用该对象的析构函数。
注意:析构函数的作用并不是删除对象,而是在撤销对象占用的内存之前完成一些清理工作,使这部分内存可以分配给新对象使用。

5.SG函数

使类外部能对类的数据成员进行修改,可选。

6.运算符重载函数

有的对象可以进行基本运算,比如说矩阵,但是普通的运算符只能支持基本数据类型的运算,如果硬生生把矩阵使用运算符连接起来,编译器就会出错,因为它不知道运算规则,不知道矩阵的元素之间怎么进行运算。
运算符重载的目的就是告诉编译器这种对象的运算规则。
语法:
返回值类型 operator[运算符](参数列表){//TODO}
运算符重载的限制
(1)不允许用户自己定义新的运算符,只能对已有的C++运算符进行重载。
(2)C++允许重载的运算符

+  -  *  /  %  ^  &  |  ~  !  =  <  >  +=  -=  *=  /=  %=  ^=  &=  |=
<<  >>  <<=  >>=  ==  !=  <=  >=  &&  ||  ++  --  ,  ->*  ->  ()  []
new  new[]  delete  delete[]

不能重载的运算符只有5个:

.     .*     ::     sizeof     ?: 

(3)不能改变运算符运算对象(即操作数)的个数。
(4)不能改变运算符的优先级别。
(5)不能改变运算符的结合性。
(6)不能有默认的参数
(7)其参数至少应有一个是类对象(或类对象的引用)。
(8)应当使重载运算符的功能类似于该运算符作用于标准类型数据时候时所实现的功能。
(9)运算符重载函数可以是类的成员函数,也可以是类的友元函数,还可以是既非类的成员函数也不是友元函数的普通函数。
运算符重载函数的位置
重载运算符的目的一般是为了进行对象的运算,上面第七条也说了必须参数必须含有类对象,因此参数应该含有对象或其引用。
1. 作为类的成员函数
当作为类的成员函数时,编译器会自动将this指针加到参数列表中,因此在考虑操作数个数时应该考虑this指针,需要两个操作数的运算符实际只需自己添加一个参数就行了。
2. 作为类的友元函数
使用friend关键字来区分友元函数,友元函数不是类的成员函数,因此实现时不需要使用类名::来限制其作用域,调用时也不需要使用类对象来调用,友元函数可以访问类的成员数据。注意友元函数的操作数中没有this指针了,需要自己添加参数。
3. 作为普通函数
作为普通函数在类外实现类对象的运算,要求类的成员数据必须为public,这可以实现但违背了类的封装性,所以不推荐使用。
三个位置实现的一个小例子

#include<iostream>
using namespace std;
class A{
    public:
    int a;
    int b;
    A operator-(A &a1);//-运算符作为成员函数实现 
    friend ostream &operator<<(ostream &out,A a1);//输出运算符只能用友元函数实现 
    A(int x,int y):a(x),b(y){}
    A();
} ;
A::A(){
    a=1;
    b=1;
}
A A::operator-(A &a1){
    A a3;
    a3.a=a-a1.a;
    a3.b=b-a1.b;
    return a3;
    }
A operator+(A a1,A a2){//类外的普通函数实现+运算符,要求成员数据必须为public 
    A a3;
    a3.a=a1.a+a2.a;
    a3.b=a1.b+a2.b;
    return a3;
}
ostream &operator<<(ostream &out,A a1){
    out<<a1.a<<"\t"<<a1.b;
    return out;
}
int main(){
    A m(1,2);
    cout<<m;
    A n(3,4);
    A q;
    q=m+n;
    cout<<q<<endl;
    cout<<m-n<<endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值