C++友元
C++友元是用friend关键修饰的函数或者类,友元用来打破类封装(忽视权限限定)
- 友元并不是说直接访问数据成员,友元只是提供一个场所赋予对象具有打破权限限定
- 友元函数
- 友元类
- 友元函数和友元类不属于当前类,实现函数或者类不需要类名限定
友元函数
- 普通函数成为类的友元函数
#include <iostream> #include <string> using namespace std; class MM { public: MM(string name, int age, int num) :name(name), age(age), num(num) {} void print(); //友元函数 friend void visitedData(); friend void visited(MM mm); protected: int num; private: int age; string name; }; void MM::print() { cout << name << "\t" << age << "\t" << num << endl; } //友元函数 void visitedData() { //name = "ILoveyou"; 不是直接访问,赋予对象的具有这样权限 //创建对象的无视权限 MM mm("girl", 18, 1001); cout << mm.name << "\t" << mm.age << "\t" << mm.num << endl; MM* p = new MM("new", 28, 1002); cout << p->name << "\t" << p->age << "\t" << p->num << endl; } void visited(MM mm) { cout << mm.name << "\t" << mm.age << "\t" << mm.num << endl; } int main() { MM girl("girl", 19, 1002); //girl.name="name"; //类外只能访问public girl.print(); visitedData(); visited(girl); return 0; }
- 以另一个类的成员函数为友元函数
#include <iostream> #include <string> using namespace std; //前向声明 class A; class B { public: B(int b) :b(b) {} void printA(A object); private: int b; }; class A { public: A(int a) :a(a) {} friend void B::printA(A object); private: int a; }; void B::printA(A object) { cout << object.a << endl; } int main() { B b(111); A a(222); b.printA(a); return 0; }
//A 以B的成员函数为友元函数,B又以A类的成员函数为友元,如果存在这种需求,代码设计有问题,C++允许这种关系
友元类
#include <iostream> #include <string> using namespace std; class MM { friend class Boy; //声明boy类是MM友元类 public: MM(string name) :name(name) {} private: string name; }; //友元类中,MM类的对象无视权限 class Boy { public: Boy() :mm("mm") { pObject = new MM("Object"); } void print() { cout <<"访问私有属性:" << mm.name << endl; cout << "访问私有属性:" << pObject->name << endl; MM* pMM = new MM("new"); cout << "访问私有属性:" << pMM->name << endl; } private: MM mm; MM* pObject; }; //互为友元类--->知道有这么回事就行,不需要自己写这样代码 class A { public: friend class B; void printA(); private: string a_name="A"; }; class B { public: friend class A; void printB() { A a; cout << a.a_name << endl; } private: string b_name="B"; }; void A::printA() { B b; cout << b.b_name << endl; } int main() { Boy boy; boy.print(); B b; b.printB(); A a; a.printA(); return 0; }
小试牛刀
//自己写个友元案例,测试打破权限这个功能即可
C++类型转换
构造的方式做转换
#include <iostream> using namespace std; int main() { int num = 1.11; cout << num << endl; int cnum = (int)1.11; cout << cnum << endl; int cppnum = int(1.22); //C++强制类型转换 cout << cppnum << endl; return 0; }
static_cast类型转换
类似C语言的强制类型转换,按照C++的说法 比C语言的更为安全
- 基本数据类型的强制转换
- 空指针转换目标类型指针
- 不能操作带const属性的类型
//static_cast<要转换的类型>(要转换目标) //要转换的类型: 数据类型 //要转换目标 可以是表达式,或者常量,都可以 #include <iostream> using namespace std; void test_static_cast() { //No.1 基本数据类型的强制转换 int num = static_cast<int>(1.111); //No.2 空类型指针的转换 double* pD = new double(1.11); void* pVoid = static_cast<void *>(pD); //No.3 不能做const属性的类型的转换 //增加const属性 //不能去掉const属性 int number = 11; const int cNum = static_cast<const int >(number); const int ccNum = number; const int data = 1; int* pData = (int *)(&data); //C语言强制类型转换 //int* pcData = static_cast<int*>(&data); //错误 } int main() { test_static_cast(); return 0; }
const_cast类型转换
- 去掉const属性(提供一个可以修改接口去操作const数据类型)
- 加上const属性(用的少一点)
#include <iostream> using namespace std; class Str { public: //去掉const属性 Str(const char* str) :str(const_cast<char*>(str)) {} void print() { cout << str << endl; } private: char* str; }; void test_const_cast() { //增加const属性 const int data = 1; int* pData = const_cast<int*>(&data); *pData = 1001; //不会作用到const变量,只是单纯提供一个接口 cout <<"data:"<< data << endl; cout << "*pData:" << *pData << endl; cout << &data << endl; cout << pData << endl; Str str("ILoveyou"); //错误,C++对于const要求更为严格 str.print(); char sstr[20] = "ILoveyoud"; Str str2(sstr); str2.print(); //3.引用类型 Test test; const Test& c_test = test; //c_test.print(); //常属性的对象只能调用常成员函数 Test& m_test = const_cast<Test&>(c_test); m_test.print(); } int main() { test_const_cast(); return 0; }
reinterpreat_cast类型转换
把指针转换为一个整数,又可以把整数转换为一个指针,指针的效果依然有效(认识知道有这么回事即可)
#include <iostream> using namespace std; int Max(int a, int b) { return a > b ? a : b; } //官方案例 unsigned short Hash(void* p) { unsigned int val = reinterpret_cast<unsigned int>(p); return (unsigned short)(val ^ (val >> 16)); } void test_reinterpret_cast() { int* p = reinterpret_cast<int*>(0); //p=nullptr; //官方案例 int a[20]; for (int i = 0; i < 20; i++) cout << Hash(a + i) << endl; //允许将任何指针转换为任何其他指针类型。 也允许将任何整数类型转换为任何指针类型以及反向转换 int* num = reinterpret_cast<int*>(Max); //把函数地址转换为int类型的数字 cout << *num << endl; auto pMax = reinterpret_cast<int(*)(int, int)>(num); cout << "max:" << pMax(1, 2) << endl; } int main() { test_reinterpret_cast(); return 0; }