文章目录
11.8
2.友元函数与成员函数的区别是什么?
成员函数是类定义的一部分,由类生成的所有对象均会共享一组类的成员函数。成员函数能够访问类内的所有数据成员
友元函数是一个拥有特殊访问权限的非成员函数,可以访问类内的私有成员,但是并不能隐式的访问,必须通过成员运算符的方式来访问类对象的数据成员。
3. 非成员函数必须是友元才能访问类成员吗?
不正确
从访问控制方式上说,非成员函数可以直接通过类对象访问公有的数据接口,但是不能访问私有的数据接口。
通过友元函数,可以和类的成员函数一样直接访问类内的所有数据成员和函数,包括私有的数据成员和函数。
因此友元的访问权限更大,一般的非成员函数只能访问类提供的公有数据接口。
5. 哪些运算符不能重载
sizeof运算符
.成员运算符
.*成员指针运算符
:: 作用域解析运算符
?: 条件运算符
typeid 一个RTTI运算符
const_cast 强制类型转换运算符
dynamic_cast 强制类型转换运算符
reintepret_cast 强制类型转换运算符
static_cast强制类型转换运算符
6. 在重载= , () , [] , -> 时,有什么限制
运算符重载的基本四条限制
- 重载运算符至少有一个参数是用户自定义的类型
- 使用的运算符不能违反该运算符本身的语法规则
- 不能创建新的运算符
- 部分运算符不能重载
特殊:大多数运算符可以通过成员函数或非成员(友元)函数进行重载,但上述的几个只能通过成员函数进行重载,不能通过友元函数进行重载
1和4 比较重要:友元函数和乘号*运算符重载的写法
class Stonewt
{
public:
//使用成员函数重载的乘法运算符
Stonewt operator*(double a) const;
//使用友元函数,将乘法运算符调换顺序
friend Stonewt operator*(double a, Stonewt s);
};
//使用成员函数进行运算符重载(要充分利用类提供的构造函数)
Stonewt Stonewt::operator*(double a) const
{
return Stonewt(a * this->pounds); //直接使用有参构造函数创建一个新对象
}
//使用友元函数,将乘法运算符调换顺序
Stonewt operator*(double a, const Stonewt s)
{
return Stonewt(a * s.pounds);
}
1. 乘法运算符重载,不要自己重新再写,要充分利用构造函数来创建新对象,修改构造函数的形参形式,来完成乘法计算,这样程序最简洁
2. 使用友元函数可以更改乘法顺序
7 Vector矢量类转换为double的矢量长度的转换函数
//转换函数没有返回类型,没有参数,但必须返回转换后的值
class Vector
{
operator double()
{
return mag;
}
}
//调用
void test01()
{
VECTOR::Vector v(3, 4);
double a = double(v); //显示调用转换函数
cout << a << endl;;
cout << double(v) << endl; //显示调用转换函数
}
int main()
{
test01();
return 0;
}
11.9 编程练习
1 通过基类的引用,来指向派生类的对象,而无需强制类型转换
函数里,通过基类的引用,来指向派生类的对象,而无需强制类型转换,fstream是基类ostream的派生类,所以可以在ostream类型对象cout的参数中直接使用fstream类对象fout,来完成对文件的输出
//此成员函数重载了<<运算符,可以输出Vector类对象(采用链式编程)
std::ostream& operator<<(std::ostream& os, const Vector& v)
2 修改类的私有数据成员和方法,保持公有方法及其参数不变,可确保程序正常使用类不受影响
5. 使用枚举类型来实现切换不同的工作模式
class Stonewt
{
public:
enum Mode { stone_mode, poudes, floatpounds };
Mode mode;
}
std::ostream& operator<<(std::ostream& os, const Stonewt& s)
{
if (s.mode == Stonewt::Mode::stone_mode)
os << "英石模式:"<< s.stone << " stone, " << s.pds_left << " pounds\n";
else if (s.mode == Stonewt::Mode::floatpounds)
os << "浮点磅模式:" << s.pounds << " pounds\n";
else //默认整数磅模式
os << "整数磅模式:" << int(s.pounds + 0.5)<<" pounds\n";
return os;
}
在加减乘除等产生新的对象的运算符重载时,尽可能使用构造函数,通过形参的变化来得到新的对象。
6 初始化对象数组的方式, bool类型返回值函数的简单写法
Stonewt stone_arr[SIZE] = { 23.6, Stonewt(8,0.3), Stonewt(23,0.2) };
return pounds < s.pounds; //666写法