C++ Trick:不使用friend,怎么访问private成员变量?

简介: 想知道怎么不使用friend,访问private的成员变量?有方法,但不鼓励……

想知道怎么不使用friend,访问private的成员变量?


有方法,但不鼓励……


方法一


#include<iostream>
usingnamespacestd;
classSensei {
public:
   Sensei(int h, int w, char c):height(h), weight(w), cup(c) {}
private:
   int height;
   int weight;
   char cup;
};

intmain() {
   Sensei sensei(160, 80, 'B');
   int height = *(int*)&sensei;
   int weight = *((int*)&sensei + 1);
   char cup = *(char*)((int*)&sensei + 2);

   cout<<height<<endl;
   cout<<weight<<endl;
   cout<<cup<<endl;
}


存在内存对齐的时候,这个代码未必有效。主要就是手撸的内存偏移就不准了。当然如果你知道你的编译器是怎么个对齐规则,你也可以继续用。比如我们调换cup和weight的顺序。


#include <iostream>
using namespace std;
class Sensei {
public:
    Sensei(int h, int w, char c):height(h), weight(w), cup(c) {}
private:
    int height;
    char cup;
    int weight;
};
int main() {
    Sensei sensei(160, 80, 'B');
    int height = *(int*)&sensei;
    char cup = *(char*)((int*)&sensei + 1);
    int weight = *((int*)&sensei + 2);
    cout<<height<<endl;
    cout<<weight<<endl;
    cout<<cup<<endl;
}


在我们机器上是4字节对齐的,所以虽然cup是char类型,但是会空余3个byte之后才是weight。


当然除了内存对齐,还有可能有虚函数,占用额外内存空间。不过你既然已经能看到这了,说明自己清楚内存布局的各种问题,自己手撸吧,不介绍了。本身这个文章也是不鼓励实际应用的,仅供延伸思路。


方法二


定义一个同样字段的类(主要是字段类型和顺序要相同)来强制类型转换。


#include <iostream>
using namespace std;
class Sensei {
public:
    Sensei(int h, int w, char c):height(h), weight(w), cup(c) {}
private:
    int height;
    char cup;
    int weight;
};
struct Actor {
    int height;
    char cup;
    int weight;
};
int main() {
    Sensei sensei(160, 80, 'B');
    Actor actor = *((Actor*)&sensei);
    // 或者
    //Actor actor = *(reinterpret_cast<Actor*>(&sensei));
    cout<<actor.height<<endl;
    cout<<actor.weight<<endl;
    cout<<actor.cup<<endl;
}


方法三


方法三,比较Trick了。但比前两种反而有使用场景。比如我们要做UT(单元测试)的时候,测试类的某些数据成员是private的,并且没提供对外set的方法。但我们想hack一些数据进去,做测试。这时候这个Sensei类的定义是在一个独立头文件中,比如sensei.h。我们在ut的的cpp或头文件中include它,这种情况都不需要像前面两种那样脱裤子放屁。


// sensei.h
class Sensei {
public:
    Sensei(int h, int w, char c):height(h), weight(w), cup(c) {}
private:
    int height;
    char cup;
    int weight;
};


我们直接用宏替换就好了,把private替换成public。并且这个其实也是做ut时候的常规做法……


// test_sensei.cpp
#include <iostream>
using namespace std;
#define private public
#include "sensei.h"
#undef private
int main() {
    Sensei sensei(160, 80, 'B');
    cout<<sensei.height<<endl;
    cout<<sensei.cup<<endl;
    cout<<sensei.weight<<endl;
    return 0;
}


相关文章
|
2月前
|
存储 C++
C++语言中指针变量int和取值操作ptr详细说明。
总结起来,在 C++ 中正确理解和运用 int 类型地址及其相关取值、设定等操纵至关重要且基础性强:定义 int 类型 pointer 需加星号;初始化 pointer 需配合 & 取址;读写 pointer 执向之处需配合 * 解引用操纵进行。
169 12
|
4月前
|
机器学习/深度学习 存储 算法
基于 C++ 布隆过滤器算法的局域网上网行为控制:URL 访问过滤的高效实现研究
本文探讨了一种基于布隆过滤器的局域网上网行为控制方法,旨在解决传统黑白名单机制在处理海量URL数据时存储与查询效率低的问题。通过C++实现URL访问过滤功能,实验表明该方法可将内存占用降至传统方案的八分之一,查询速度提升约40%,假阳性率可控。研究为优化企业网络管理提供了新思路,并提出结合机器学习、改进哈希函数及分布式协同等未来优化方向。
93 0
|
12月前
|
存储 编译器 C++
【C++】深入探索类和对象:初始化列表及其static成员与友元(一)
【C++】深入探索类和对象:初始化列表及其static成员与友元
233 2
|
7月前
|
安全 C++
【c++】继承(继承的定义格式、赋值兼容转换、多继承、派生类默认成员函数规则、继承与友元、继承与静态成员)
本文深入探讨了C++中的继承机制,作为面向对象编程(OOP)的核心特性之一。继承通过允许派生类扩展基类的属性和方法,极大促进了代码复用,增强了代码的可维护性和可扩展性。文章详细介绍了继承的基本概念、定义格式、继承方式(public、protected、private)、赋值兼容转换、作用域问题、默认成员函数规则、继承与友元、静态成员、多继承及菱形继承问题,并对比了继承与组合的优缺点。最后总结指出,虽然继承提高了代码灵活性和复用率,但也带来了耦合度高的问题,建议在“has-a”和“is-a”关系同时存在时优先使用组合。
362 6
|
11月前
|
存储 编译器 C++
【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)
本文介绍了C++中类和对象的高级特性,包括取地址运算符重载、构造函数的初始化列表、类型转换、static修饰成员、友元、内部类及匿名对象等内容。文章详细解释了每个概念的使用方法和注意事项,帮助读者深入了解C++面向对象编程的核心机制。
268 5
|
11月前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
552 4
|
12月前
|
编译器 C语言 C++
C++入门3——类与对象2-2(类的6个默认成员函数)
C++入门3——类与对象2-2(类的6个默认成员函数)
109 3
|
12月前
|
存储 编译器 数据安全/隐私保护
【C++篇】C++类与对象深度解析(四):初始化列表、类型转换与static成员详解2
【C++篇】C++类与对象深度解析(四):初始化列表、类型转换与static成员详解
146 3
|
12月前
|
编译器 C++
【C++篇】C++类与对象深度解析(四):初始化列表、类型转换与static成员详解1
【C++篇】C++类与对象深度解析(四):初始化列表、类型转换与static成员详解
238 3
|
12月前
|
安全 编译器 C++
【C++篇】C++类与对象深度解析(三):类的默认成员函数详解
【C++篇】C++类与对象深度解析(三):类的默认成员函数详解
84 3