C++友元

简介: C++友元

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;
}
目录
相关文章
|
2月前
|
存储 编译器 C++
【C++】深入探索类和对象:初始化列表及其static成员与友元(一)
【C++】深入探索类和对象:初始化列表及其static成员与友元
|
1月前
|
存储 编译器 C++
【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)
本文介绍了C++中类和对象的高级特性,包括取地址运算符重载、构造函数的初始化列表、类型转换、static修饰成员、友元、内部类及匿名对象等内容。文章详细解释了每个概念的使用方法和注意事项,帮助读者深入了解C++面向对象编程的核心机制。
83 5
|
2月前
|
编译器 C语言 C++
C++入门4——类与对象3-1(构造函数的类型转换和友元详解)
C++入门4——类与对象3-1(构造函数的类型转换和友元详解)
29 1
|
2月前
|
C++
【C++】深入探索类和对象:初始化列表及其static成员与友元(二)
【C++】深入探索类和对象:初始化列表及其static成员与友元
|
2月前
|
编译器 C++
【C++】深入探索类和对象:初始化列表及其static成员与友元(三)
【C++】深入探索类和对象:初始化列表及其static成员与友元
|
2月前
|
C++
C++入门4——类与对象3-2(构造函数的类型转换和友元详解)
C++入门4——类与对象3-2(构造函数的类型转换和友元详解)
29 0
|
3月前
|
编译器 数据安全/隐私保护 C++
C++(十四) friend友元
友元机制允许非成员函数或类访问私有成员,提高程序效率,但会破坏封装性。友元可以是函数或类,并以关键字`friend`声明。友元函数不是成员函数,需通过对象访问私有成员。友元类使所有成员函数可访问另一个类的私有成员,常用于简化开发。友元声明位置灵活,但不影响访问控制。使用友元需注意其单向性和非传递性。
|
5月前
|
C++
C++友元函数和友元类的使用
C++中的友元(friend)是一种机制,允许类或函数访问其他类的私有成员,以实现数据共享或特殊功能。友元分为两类:类友元和函数友元。类友元允许一个类访问另一个类的私有数据,而函数友元是非成员函数,可以直接访问类的私有成员。虽然提供了便利,但友元破坏了封装性,应谨慎使用。
101 9
|
5月前
|
编译器 数据安全/隐私保护 C++
C++一分钟之-属性友元与访问控制
【7月更文挑战第9天】C++中的友元机制允许非成员函数或类访问私有和保护成员,打破了封装性。友元需在类内声明,常见的错误包括忘记声明、过度使用及误解友元的非继承性。要避免错误,应明确声明友元,限制其使用,并理解其局限。示例展示了如何声明和使用友元函数来访问私有数据。谨慎使用友元以保持代码的健壮性和可维护性。
58 1