引用
引用类型不能更改
struct Base
{
int x;
int y;
Base(int x,int y)
{
this->x = x;
this->y = y;
}
};
void PrintByPoint(Base* pb)
{
printf("%d %d\n",pb->x,pb->y);
pb = (Base*)0x123456;
//为所欲为...
}
void PrintByRef(Base& refb,Base* pb)
{
printf("%d %d\n",refb.x,refb.y);
Base b1(21,31);
//&refb = b1; //引用不能重新赋值
refb = b1; //这个不是重新赋值,这个是把b1的值赋给refb代表的对象
printf("%d %d\n",pb->x,pb->y);
}
为了避免出现这种情况,可以将refb声明为常量,不可修改:
void PrintByRef(const Base& refb)
{
printf("%d %d\n",refb.x,refb.y);
Base b1(21,31);
//&refb = b1; //引用不能重新赋值
//refb = b1; //不允许 ,因为定义成了常量类型
}
与指针的反汇编区别
void demo(int& arg)
{
arg=1;//与指针的差别 前面可以不用加* 给指针指向的地址赋值.相当于给main那里的a赋值
}
int main(int argc,char* argv[])
{
int a=10;
demo(a);//在c++中 demo的参数a有可能是int 类型 有可能会是int类型的引用 这里直接传变量
return 0;
}
//在反汇编中 上面的反汇编代码同下面的指针类型没差别:
void demo(int* arg)
{
*arg=1;
}
int main(int argc,char* argv[])
{
int a=10;
demo(&a);//在c++中 demo的参数a有可能是int 类型 有可能会是int类型的引用 这里需要传变量地址
return 0;
}
唯一的区别就是指针传参,指针可以指向别的地方(乱指会出错).
而引用的话 编译器不允许再指向别的地方
总结
- 引用和指针在底层汇编阶段没有任何区别,都是地址传递。
- 不同:指针可能出现地址乱指的问题,而引用则不会,改变引用的值实际上是改变变量地址上的值,而不是变量的地址。
- 引用是C++中特有类型。
- 引用类型只能赋值一次,不能重新赋值。
- 引用只是变量的一个别名。
- 引用可以理解成是编译器维护的一个指针,但并不占用空间。
- 使用引用可以像指针那样去访问、修改对象的内容,但更安全。
友元函数
class Person
{
private:
int x;
int y;
public:
Person(int x,int y)
{
this->x = x;
this->y = y;
}
//声明友元函数
//friend void Print(const Person& refPer);
};
void Print(const Person& refPer)
{
printf("%d\n",refPer.x);
printf("%d\n",refPer.y);
}
int main(int argc, char* argv[])
{
Person p(1,2);
Print(p);
return 0;
}
还有友元类,本质都是在需要使用的类里面声明外部某函数 某类是朋友,可以调用本类中的私有成员
总结
什么情况下需要友元函数:
(1) 运算符重载的某些场合需要使用友元.
(2) 两个类要共享数据的时候.
友元函数和类的成员函数的区别
(1) 成员函数有this指针,而友元函数没有this指针
(2) 友元函数是不能被继承的,就像父亲的朋友未必是儿子的朋友
运算符重载
class Number
{
private:
int lowValue;
int highValue;
public:
Number(int lowValue,int highValue);
void Print();
//写运算符重载一定要注意,因为它本身也是一个函数,是函数就有返回值.它的这个运算返回值必须是它自己的类型 Int i; i++ i加完还是int 所以 这里运算符重载的子程序运算完后 返回值类型应该还是demo
Number operator++();
Number operator--();
Number operator+(const Number& p);
Number operator-(const Number& p);
Number operator*(const Number& p);
Number operator/(const Number& p);
//但是如果重载的是大于这类的运算符,返回值类型应该是逻辑类型
bool operator>(const Number& p);
bool operator<(const Number& p);
bool operator==(const Number& p);
};
Number::Number(int lowValue,int highValue)
{
this->lowValue = lowValue;
this->highValue = highValue;
}
void Number::Print()
{
printf("%d\n",lowValue);
printf("%d\n",highValue);
}
Number Number::operator++()
{
lowValue++;
highValue++;
return *this;
}
Number Number::operator--()
{
lowValue--;
highValue--;
return *this;
}
Number Number::operator+(const Number& p)
{
this->highValue = this->highValue + p.highValue;
this->lowValue = this->lowValue + p.lowValue;
return *this;
}
Number Number::operator-(const Number& p)
{
this->highValue = this->highValue - p.highValue;
this->lowValue = this->lowValue - p.lowValue;
return *this;
}
Number Number::operator*(const Number& p)
{
this->highValue = this->highValue * p.highValue;
this->lowValue = this->lowValue * p.lowValue;
return *this;
}
Number Number::operator/(const Number& p)
{
this->highValue = this->highValue / p.highValue;
this->lowValue = this->lowValue / p.lowValue;
return *this;
}
bool Number::operator>(const Number& p)
{
if(this->highValue > p.highValue)
{
return true;
}
return false;
}
bool Number::operator<(const Number& p)
{
if(this->highValue < p.highValue)
{
return true;
}
return false;
}
bool Number::operator==(const Number& p)
{
if(this->highValue == p.highValue)
{
return true;
}
return false;
}
void Test()
{
Number p(1,2),p2(3,4);
p++;
p.Print();
p--;
p.Print();
p = p+p2;
p.Print();
}
int main(int argc, char* argv[])
{
Test();
return 0;
}
总结
- 运算符重载就是函数替换
- . :: ?: sizeof # 不能重载
- 除了在结构体内部定义,使用友元函数也可以实现(+±-这种需要用到this指针的不适用)
- 有些情况下,一定要用到友元函数…
本节练习:
1、定义一个类,使用友元函数实现:+、-、*、/、>、<、>=、<=
等运算符重载(什么情况下,一定要用友元函数?).
运算符重载通常可以用成员函数或者非成员函数(友元函数)来实现。使用哪种方法取决于操作数和操作符的类型。
在某些情况下,如果我们需要访问类的私有成员变量或函数,而这些变量或函数又不是该类的成员函数,则需要使用友元函数来重载运算符。因为只有友元函数能够访问类的私有成员。
具体来说,以下情况下必须使用友元函数来重载运算符:
- 当操作符的左操作数是一个自定义类型的对象,右操作数不是自定义类型的对象时,必须使用友元函数。
- 当我们需要访问私有成员变量时,必须使用友元函数。
例如,如果我们想要重载“+”运算符来实现两个自定义类型对象的相加操作,而其中一个操作数是 int 类型,则需要使用友元函数。因为 int 类型不是我们自定义的类型,不能访问我们类中的私有成员变量和函数。
#include"c++test.h"
#include<stdio.h>
#include<Windows.h>
#include<stdio.h>
#include<Windows.h>
class Sub; // 提前声明 Sub 类
class Base
{
private:
int x;
int y;
public:
Base(int w, int z)
{
this->x = w;
this->y = z;
}
bool operator==(const Base& p) const; // 修改 operator== 函数的参数、返回值和修饰符
int operator+(const Sub& p); // 添加 operator+ 函数
};
class Sub
{
private:
int a;
int b;
public:
Sub(int x, int y)
{
this->a = x;
this->b = y;
}
friend int Base::operator+(const Sub& p); // 修改 operator+ 函数的参数和返回值
};
bool Base::operator==(const Base& p) const // 修改 operator== 函数的参数、返回值和修饰符
{
if (this->x == p.x && this->y == p.y)
return true;
else
return false;
}
int Base::operator+(const Sub& p) // 添加 operator+ 函数
{
return this->x + p.a; // 将 pb 的 x 值加上 pc 的 a 值并返回
}
int main(int argc, char* argv[])
{
Base pb(1, 2);
Sub pc(1, 2);
int k = 1;
int sum = pb + pc; // 先将 pb 和 pc 相加
printf("%d", sum); // 再打印出结果
return 0;
}
是用友元函数进行函数重载