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;
}