5.友元函数和友元类
// 友元函数:如果一个函数 func(), 它是类A 的友元函数,该函数可以通过A的对象使用A 的所有成员(包括私有成员)
// 定义方式:
// 1、在类中写出函数声明
// 2、在函数声明前加一个关键字 friend
// 定义方式:
// 1、在类中写出函数声明
// 2、在函数声明前加一个关键字 friend
// 特点:
// 1、友元函数不是类的内部函数,是一个外部函数,所以没有this 指针
// 2、友元函数的声明不受访问控制符影响,可以放到类的任意位置
// 3、友元函数破坏了类的封装性,轻易不要使用
// 1、友元函数不是类的内部函数,是一个外部函数,所以没有this 指针
// 2、友元函数的声明不受访问控制符影响,可以放到类的任意位置
// 3、友元函数破坏了类的封装性,轻易不要使用
class Student
{
friend void showS(Student &s);
public:
Student(int id, char *name)
{
this->id = id;
this->name = name;
}
void show(Address &add);
{
friend void showS(Student &s);
public:
Student(int id, char *name)
{
this->id = id;
this->name = name;
}
void show(Address &add);
void printS()
{
printf ("id = %d, name = %s\n", id, name);
}
private:
int id;
char *name;
};
{
printf ("id = %d, name = %s\n", id, name);
}
private:
int id;
char *name;
};
void showS(Student &s)
{
printf ("id = %d, name = %s\n", s.id, s.name);
}
{
printf ("id = %d, name = %s\n", s.id, s.name);
}
// 友元类:如果一个类A 是 类B 的友元类,则类A中所有函数都是类B 的友元函数
void Student::show(Address &add)
{
printf ("id = %d, name = %s\n", id, name);
printf ("%s省%s市%s区%s镇\n", add.shen, add.city, add.qu, add.cun);
}
printf ("id = %d, name = %s\n", id, name);
printf ("%s省%s市%s区%s镇\n", add.shen, add.city, add.qu, add.cun);
}
6.运算符重载
friend Complex add(Complex &c1, Complex &c2);friend Complex operator+(Complex &c1, Complex &c2);
friend Complex operator+(Complex &c1, int num);
// 1、写出函数函数名:operator + 要重载的运算符 operator*、operator-
// 2、根据操作写出函数的形参:operator+(Complex &c1, Complex &c2)
// 3、根据需要写出返回值类型:Complex operator+(Complex &c1, Complex &c2)
// 4、实现功能
// 2、根据操作写出函数的形参:operator+(Complex &c1, Complex &c2)
// 3、根据需要写出返回值类型:Complex operator+(Complex &c1, Complex &c2)
// 4、实现功能
Complex operator+(Complex &c1, Complex &c2) // Complex operator+(Complex * const pc, Complex &c2)
{
Complex tmp(c1.a+c2.a, c1.b+c2.b);
return tmp;
}
{
Complex tmp(c1.a+c2.a, c1.b+c2.b);
return tmp;
}
// 运算符重载,同一种运算,全局方式和内部方式只能存在一种
// 使用全局函数重载运算符
Complex c1(1,2), c2(3,4),c3;
// 编译器知道如何运算?
// 自定义类型 编译器不知道运算规则,所以不允许直接进行运算
// c3 = add(c1, c2);
// c3 = operator+(c1, c2);
// 自定义类型 编译器不知道运算规则,所以不允许直接进行运算
// c3 = add(c1, c2);
// c3 = operator+(c1, c2);
// 1、编译器发现 c1 和 c2 是自定义类型
// 2、它们要进行 + 运算
// 3、调用函数执行相应的功能: operator+(c1, c2)
// 4、如果存在 operator+(c1, c2)则执行成功,如果不存在,则报错
// 2、它们要进行 + 运算
// 3、调用函数执行相应的功能: operator+(c1, c2)
// 4、如果存在 operator+(c1, c2)则执行成功,如果不存在,则报错
7.一元运算符
Complex& operator--() // Complex& operator--(Complex *const this)
{
--a; // -- this.a;
--b; // -- this.b;
return *this;
}
{
--a; // -- this.a;
--b; // -- this.b;
return *this;
}
Complex operator--(int) // Complex& operator--(Complex *const this, int)
{
Complex tmp = *this;
a--;
b--;
return tmp;
}
{
Complex tmp = *this;
a--;
b--;
return tmp;
}
// Complex& operator++() // Complex& operator++(Complex *const this)
// {
// ++a; // ++ this.a;
// ++b; // ++ this.b;
// return *this; //返回的是this指针
// }
// {
// ++a; // ++ this.a;
// ++b; // ++ this.b;
// return *this; //返回的是this指针
// }
Complex& operator++(Complex &c)
{
++c.a;
++c.b;
return c;
}
{
++c.a;
++c.b;
return c;
}
// 区分前置++和后置++:通过一个int型占位参数来区分,后置++函数中有一个int型的占位参数
Complex operator++(Complex &c, int)
8.左移与右移操作符的重载
friend ostream& operator<<(ostream &out, Complex &c);
// 左移操作符是不能重载为内部函数,原因在于如果重载为内部函数,则应该放到 ostream类中
// 但是 ostream 这个类是不允许修改的,所以只能全局的方式和友元函数重载左移运算符
ostream& operator<<(ostream &out, Complex &c)
{
out << c.a << " + " << c.b << "i";
return out;
}
// 但是 ostream 这个类是不允许修改的,所以只能全局的方式和友元函数重载左移运算符
ostream& operator<<(ostream &out, Complex &c)
{
out << c.a << " + " << c.b << "i";
return out;
}
// 运算符重载在无法修改左操作数时候只能使用全局方式重载
Complex c1(1,2);
// operator<< (operator<<(cout, c1), endl);
cout << c1 << endl;
cout << c1 << endl;