在本章主要简述定义一个C++类的时候须要注意的细节,包括初始化列、操做符重载等。
实例讲解代码为:ios
#ifndef COMPLEX_H #define COMPLEX_H #include<iostream> using std::ostream; using std::endl; using std::cin; using std::ends; using std::cout; class Complex { public: Complex(double, double); Complex(const Complex&); ~Complex(); double Get_re()const; double Get_img()const; Complex& operator +=(const Complex &); private: double re; double img; friend Complex& _add(Complex*, const Complex&);//因为须要去除private元素,因此这设置为友元,在调用一个函数的友元的时候,其也具有访问另外一个对象private的能力 }; inline Complex::Complex(double re = 0, double img = 0) :re(re), img(img) { }; inline Complex::Complex(const Complex & comp) { this->re = comp.re; this->img = comp.img; cout << "调用了复制构造函数" << ends; } inline Complex::~Complex() { cout << "析构函数被调用" << endl; }; inline double Complex::Get_re() const { return re; }; inline double Complex::Get_img() const { return img; }; inline Complex& _add(Complex* ths, const Complex& plus_ele) { ths->re += plus_ele.re; ths->img += plus_ele.img; return(*ths); } //下面是包含this的重载运算符 inline Complex& Complex::operator +=(const Complex& plus_ele) { return _add(this, plus_ele); } //下面的都是不包含this的重载运算符 inline Complex operator +(const Complex & comp1, const Complex & comp2) { return Complex(comp1.Get_re() + comp2.Get_re(), comp1.Get_img() + comp2.Get_img()); } inline ostream& operator <<(ostream& os, const Complex& comp)//主要是为了应对连续使用<<的状况 { return os << comp.Get_re() << "+" << comp.Get_img()<<"i"; } inline void test_reference(Complex com) { cout << com << ends; } #endif // !COMPLEX_H
主要是为了防止经过对象直接更改内部的值,固然能够经过成员函数来更改其中的值,目的是增长类的封装性。函数
若是使用一个值来传递的化咱们能够定义一个全局函数接受一个Complex为入口参数:this
inline void test_reference(Complex com) { cout << com << ends; }
同时在析构函数加入:spa
inline Complex::~Complex() { cout << "析构函数被调用" << endl; };
调用该函数的结果为:
因此在传值得时候建立了一个局部对象,使用复制构造函数度这个局部变量进行了初始化,在离开做用域的时候会销毁这个局部变量,所以会调用析构函数,这也太麻烦了。code
主要缘由在于若是返回的是一个对象的话,这个对象是也是个临时对象,将会在调用该函数的那一行后被析构。咱们加入一行对象
inline Complex test_reference1(Complex com) { return com; }
调用方式为:继承
Complex cmp1(1, 2); Complex cmp2(1,1); cmp2=test_reference1(cmp1);
结果为:
两次调用了析构函数与复制构造函数,缘由在于首先在传递参数的时候在函数内部构造了一个局部对象com,在返回一个对象后悔临时再构建一个对象用于给cmp2赋值,随后到下一行这个临时变量就被析构函数析构了。ip
没啥好说的,就是为了防止在局部函数中更改了原始数据,若是确实有这个需求除外。内存
初始化列表初始化对象中的变量的做用是避免了初始化内部对象+赋值的操做,若是使用的是初始化列表,那么其使用的是复制构造函数,这样节省了大量的时间。ci
在进行操做符重载的时候能够分为两类
一、包含this的成员函数(成员);
二、不包含this的非成员函数(全局);
这样区别的理由是这个操做符的对象结果是否又被赋值给了这个操做符的入口参数?若是被赋值的对象为入口参数变量如+=,-=等,那么这个操做符重载应该是类的成员函数,例如cmp1+=cmp2的时候左侧cmp1既是入口参数也是被赋值的对象,所以这个操做符应该被定义为成员函数。若是这个操做符的结果并未赋值给入口参数变量,那么应当定义为全局运算符重载,如—,+等。
也就是说在一个对象处理另外一个类的private数据时候是有权限的:
inline double Complex::get_sum(const Complex& comp)const { return this->re + comp.re; };
comp.re是对象comp的private数据可是在this中居然能够访问!咱们可不能够经过继承一个类来访问其私有数据来打破封装性呢?很明显不行,由于私有数据不被继承(这句话不必定对,由于子内存上仍是继承了只是不能直接访问而已)。