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;
}


相关文章
|
17天前
|
编译器 数据安全/隐私保护 C++
C++(十四) friend友元
友元机制允许非成员函数或类访问私有成员,提高程序效率,但会破坏封装性。友元可以是函数或类,并以关键字`friend`声明。友元函数不是成员函数,需通过对象访问私有成员。友元类使所有成员函数可访问另一个类的私有成员,常用于简化开发。友元声明位置灵活,但不影响访问控制。使用友元需注意其单向性和非传递性。
|
29天前
|
存储 安全 C++
C++:指针引用普通变量适用场景
指针和引用都是C++提供的强大工具,它们在不同的场景下发挥着不可或缺的作用。了解两者的特点及适用场景,可以帮助开发者编写出更加高效、可读性更强的代码。在实际开发中,合理选择使用指针或引用是提高编程技巧的关键。
23 1
|
7天前
|
JavaScript 前端开发 Java
通过Gtest访问C++静态、私有、保护变量和方法
通过Gtest访问C++静态、私有、保护变量和方法
8 0
|
1月前
|
编译器 C++ 索引
C++虚拟成员-虚函数
C++虚拟成员-虚函数
|
1月前
|
编译器 C++
virtual类的使用方法问题之C++类中的非静态数据成员是进行内存对齐的如何解决
virtual类的使用方法问题之C++类中的非静态数据成员是进行内存对齐的如何解决
|
1月前
|
编译器 C++
virtual类的使用方法问题之静态和非静态函数成员在C++对象模型中存放如何解决
virtual类的使用方法问题之静态和非静态函数成员在C++对象模型中存放如何解决
|
1月前
|
存储 算法 搜索推荐
【C++】类的默认成员函数
【C++】类的默认成员函数
|
2月前
|
存储 C++
【C++】string类的使用③(非成员函数重载Non-member function overloads)
这篇文章探讨了C++中`std::string`的`replace`和`swap`函数以及非成员函数重载。`replace`提供了多种方式替换字符串中的部分内容,包括使用字符串、子串、字符、字符数组和填充字符。`swap`函数用于交换两个`string`对象的内容,成员函数版本效率更高。非成员函数重载包括`operator+`实现字符串连接,关系运算符(如`==`, `&lt;`等)用于比较字符串,以及`swap`非成员函数。此外,还介绍了`getline`函数,用于按指定分隔符从输入流中读取字符串。文章强调了非成员函数在特定情况下的作用,并给出了多个示例代码。
|
3月前
|
安全 C++
C++一分钟之-互斥锁与条件变量
【6月更文挑战第26天】在C++并发编程中,`std::mutex`提供互斥访问,防止数据竞争,而`std::condition_variable`用于线程间的同步协调。通过`lock_guard`和`unique_lock`防止忘记解锁,避免死锁。条件变量需配合锁使用,确保在正确条件下唤醒线程,注意虚假唤醒和无条件通知。生产者-消费者模型展示了它们的应用。正确使用这些工具能解决同步问题,提升并发性能和可靠性。
45 4
|
3月前
|
安全 数据安全/隐私保护 C++
C++一分钟之-成员访问控制:public, private, protected
【6月更文挑战第20天】C++的成员访问控制涉及`public`、`private`和`protected`,影响类成员的可见性和可访问性。`public`成员对外公开,用于接口;`private`成员仅限类内部,保护数据安全;`protected`成员在派生类中可访问。常见问题包括不恰当的访问级别选择、继承中的访问权限误解及过度使用友元。通过示例展示了如何在派生类中访问`protected`成员。正确使用访问修饰符能确保代码的封装性、安全性和可维护性。
91 4