1.初始化列表
构造函数(初始参数):要初始化的成员(初始值),...
{}
建议直接使用初始化列表来初始化所有的成员
---------------------------------------------------------------------------------------------------------------------------
#include<iostream> using namespace std; class Test { public: Test():a(0),b(0){} Test(int a,int b):a(a),b(b){} void show() { cout << "a = " << a << endl; cout << "b = " << b << endl; } private: int a; const int b; }; int main() { Test t; t.show(); Test t1(10,20); t1.show(); return 0; }
2.拷贝/复制 构造函数
使用已经存在的对象拷贝或复制出一个新的对象
拷贝构造函数的参数:是本类类型的引用
使用:
构造函数(const 类名&)
{}
当没有显示定义拷贝构造函数时,编译器会自动生成
编译器默认的拷贝方式,称为浅拷贝
注意:
当成员变量有指针类型,然后在构造函数中进行了动态的内存分配,然后在析构函数中进行了动态内存的释放
,那么必须写自己的拷贝构造函数。
拷贝构造函数的调用时机:
1.用已经存在的对象构造一个新对象
Test t2(t1);
Test t2 = t1;
2.当函数的参数是对象时
void func(Test t);
3.当函数返回的是一个对象时,有些编译器(g++)会做优化
例如:
Test func() { Test t(100,200); return t; // Test tmp = t; } int func() { int a = 10; return a; //int tmp = a; } int res = func();
---------------------------------------------------------------------------------------------------------------------------
练习:深拷贝与浅拷贝,要注意double free问题
#include<iostream> using namespace std; class Test { public: Test():a(0) { b = new int(0); cout << "默认构造函数" << endl; } Test(int a,int b):a(a) { this->b = new int(b); cout << "带参数的构造函数" << endl; }//带参数的构造函数 private: Test(Test& other)//拷贝构造函数 { cout << "拷贝构造函数" << endl; this->a = other.a; this->b = new int; *(this->b) = *(other.b); } public: ~Test() { cout << "析构函数" << endl; delete b; } void show() { cout << "a = " << a << endl; cout << "b = " << *b << endl; } private: int a; int *b; }; void func(Test& t)// Test& t = t1; { t.show(); } Test func1() { Test t(100,200); return t; } int main() { Test t; t.show(); Test t1(10,20); t1.show(); cout << "---------1---------" << endl; // Test t2(t1); Test t2 = t1;//复制 t2.show(); cout << "----2-----" << endl; func(t1); cout << "--------3---------" << endl; Test t3; t3 = func1(); t3.show(); /* Test t3; t3 = t1;//复值 t3.show(); */ return 0; }
3.静态成员
为了实现一个类的多个对象之间的数据共享,C++提出静态成员的概念
静态成员变量
静态成员变量不属于某个具体的对象,属于某个类型
静态成员变量必须在类外初始化
类型 类名::静态成员变量名=初始值;
静态成员函数
专门用于处理静态成员变量
静态成员函数的调用方式:
类名::静态成员函数名();
注意:静态成员函数中没有this!!
--------------------------------------------------------------------------------------------------------------------------
#include<iostream> using namespace std; class Student { public: Student() { name = "Wuming"; count++; } ~Student() { count--; } void show() { cout << name << endl; } static int getCount()//静态成员函数 { return count; } private: string name; static int count; }; int Student::count = 0;//静态成员变量的初始化 void func() { Student sa[100] ; cout << "count = " << Student::getCount() << endl;//? } int main() { cout << "count = " << Student::getCount() << endl;//? Student s; s.show(); func(); cout << "count = " << Student::getCount() << endl;//? //cout << "count = " << s.getCount() << endl;//? return 0; }
4.友元 friend
友元是对类的封装的一个补充,
友元会赋予某些函数直接访问对象的私有成员的权限
友元函数:
普通的全局函数
friend 返回类型 函数名(参数列表);
类的成员函数
friend 返回类型 类名::成员函数名(参数列表);
友元类:
friend class 类名;
类的前置声明:
class 类名;
注:
友元关系是单向的
A是B的朋友,B不是A的朋友
友元关系是不可传递的
A是B的朋友,B是C的朋友,A不是C的朋友
-----------------------------------------------
-友元函数-------------------------------------------
---------------------------------------------
#include<iostream> using namespace std; class Test { public: Test() { a = 100; } void show() { cout << "a = " << a << endl; } friend void func(Test); private: int a; }; void func(Test t) { cout << t.a << endl; } int main() { Test t; t.show(); func(t); return 0; }
-----------------------------------------------
-----友元类----------------------------
-----------------------------------------------
#include<iostream> using namespace std; class Girl; class Boy { public: void show(Girl); private: }; class Girl { public: Girl(string name):name(name){} // friend void Boy::show(Girl); friend class Boy; private: string name; }; void Boy::show(Girl g) { cout << "this girl's name :'" << g.name << endl; } int main() { Girl girl("Hanmeimei"); Boy boy; boy.show(girl); return 0; }
5.运算符重载
在C++中,所有的运算符都被处理成函数
运算符重载的本质就是函数重载
运算符对应函数名称,操作数对应函数参数,运算结果对应函数返回值
运算符函数:
返回类型 operator运算符(参数列表);
运算符重载函数:
友元函数
函数参数与操作数个数一致!
成员函数
函数参数要比操作数少一个!因为成员函数需要一个对象来调用
----------------------------------------重载运算符+,>,<<-------
--------------------------------
-----------------------------------------------
#include<iostream> using namespace std; class Complex { public: Complex(double real=0,double imag=0) { this->real = real; this->imag = imag; } void show() { cout << "(" << real << "," << imag << "i)" << endl; } Complex operator+(Complex &c2) { cout << "operator+++++++" << endl; Complex c3; c3.real = this->real + c2.real; c3.imag = this->imag + c2.imag; return c3; } // friend Complex operator+(Complex c1,Complex c2); friend bool operator>(Complex &c1,Complex &c2); friend ostream& operator<<(ostream &out,Complex &c); private: double real; double imag; }; /* Complex operator+(Complex c1,Complex c2) { cout << "operator+++++++" << endl; Complex c3; c3.real = c1.real + c2.real; c3.imag = c1.imag + c2.imag; return c3; } */ bool operator>(Complex &c1,Complex &c2) { if(c1.real > c2.real) { return true; } else { return false; } } ostream& operator<<(ostream &out,Complex &c) { out << "(" << c.real << "," << c.imag << "i)"; return out; } int main() { Complex c1(1,2); Complex c2(2,3); Complex c3 = c1 + c2;// c3 operator+(c1,c2) // c3 c1.operator+(c2) // c3.show(); cout << c3 << endl; // cout operator<<(cout,c3) if( c1 > c2 )// bool operator>(c1,c2) { cout << "c1 > c2" << endl; } else { cout << "c1 <= c2" << endl; } return 0; }
------------------------------------------------重载运算符++--------------------------------------------------------------------
#include<iostream> using namespace std; class Time { public: Time(int m=0,int s=0):m(m),s(s){} void show() { cout << m << ":" << s << endl; } friend Time& operator++(Time&); friend Time operator++(Time&,int); private: int m; int s; }; Time& operator++(Time &t)//Time t = t1; { if(++t.s == 60) { t.s = 0; ++t.m; } return t; } Time operator++(Time &t,int) { Time tmp = t; if(++t.s == 60) { t.s = 0; ++t.m; } return tmp; } int main() { Time t; t.show(); Time t1(10,50); t1.show(); Time t2 = ++t1;// t1 operator++(t1) t2.show();//10:51 t1.show();//10:51 Time t3 = t1++;// t1 operator++(t1) t3.show();//10:51 t1.show();//10:52 //t1.operator++(int) return 0; }
------------------------------------------------重载运算符=--------------------------------------------------------------------
#include<iostream> using namespace std; class Test { public: Test():a(0) { b = new int(0); cout << "默认构造函数" << endl; } Test(int a,int b):a(a) { this->b = new int(b); cout << "带参数的构造函数" << endl; }//带参数的构造函数 Test(Test& other)//拷贝构造函数 { cout << "拷贝构造函数" << endl; this->a = other.a; this->b = new int; *(this->b) = *(other.b); } public: ~Test() { cout << "析构函数" << endl; delete b; } void show() { cout << "a = " << a << endl; cout << "b = " << *b << endl; } Test& operator=(Test &t)//赋值运算符重载函数 { cout << "operator=" << endl; //1.防止自赋值 if(this == &t) { return *this; } //2.释放原有空间 delete b; //3.分配新空间 b = new int; //4.把值拿过来 *b = *(t.b); //5.返回自引用 return *this; } private: int a; int *b; }; void func(Test& t)// Test& t = t1; { t.show(); } Test func1() { Test t(100,200); return t; } int main() { Test t; t.show(); Test t1(10,20); t1.show(); cout << "---------1---------" << endl; Test t4; t = t4 = t1;//复值 t4 operator=(t1) t4.show(); t.show(); t4 = t4; return 0; }
--------------------------------------------------------------------------------------------------------------------
练习:求两点间的距离
#include <math.h> #include <stdio.h> using namespace std; class spot { private: double x; double y; public: spot(double x,double y):x(x),y(y){} void show() { cout<<"("<<x<<","<<y<<")"<<endl; } friend double print_distance1(spot &a,spot &b);//友元函数方法 static double print_distance(spot a,spot b)//静态成员函数方法 { double s; s = sqrt((b.x - a.x) * (b.x - a.x) + (b.y - a.y) * (b.y - a.y)); return s; } }; double print_distance1(spot &a,spot &b) { double s; s = sqrt((b.x - a.x) * (b.x - a.x) + (b.y - a.y) * (b.y - a.y)); return s; } int main() { spot a(1,2); spot b(3,4); a.show(); b.show(); double s,s1; s = spot::print_distance(a,b); printf("方法一:两点间距离为:%lf\n",s); s1 = print_distance1(a,b); printf("方法二:两点间距离为:%lf\n",s); return 0; }