c++高级---不修改源类访问源类中的私有成员

C++之友元函数不能访问类的私有成员 无法解决的问题:类中声明,类外定义的成员函数,导致无法访问类中的私有成员函数 去掉using namespace std; 改变#include <iostream>啥的都没用 苍了个天,走过路过的帮个忙? 真的是头大,跟着视频敲代码,人家的代码好好的,就我的出错。本来出现红色波浪线就不舒服,但好在能编译通过,但是,在类中的函数声明和定义分离的时候,编译就不通过,成员函数就无法... 阅读详情

转自:http://blog.youkuaiyun.com/steedhorse/article/details/1263127

前几天,在论坛里看到一个帖子,内容是:

  1. class a  
  2. {  
  3. private:  
  4.     int k;  
  5. };  
class a{private:    int k;};

要求不用友元,不在这个类里添加任何代码,去访问成员变量k。

能做出的高手,请贴出完整源码,以便大家测试。

========================================

 

这道题目本身所要解决的问题并没有多少现实意义,但如果试着去解决它,以及比它更复杂的情况,我认为至少对理解C++的对象模型是很有帮助的。

 

开始讨论之前不得不说,这道题做为一个题目存在逻辑上的重大缺陷:“不给类增加一行代码”,我实在想不出如何在验正解题人所提供方案的正确性。只有一个private,难道用解题人所提供的读出方案来验证他自己所提供的写入方案?你用你的方法读出来,然后告诉我那就是你用你的方法写进去的值——那能让人信服吗?所以我决定还是把问题改一改,并稍微具体化如下:

  1. class Test {  
  2. public:  
  3.     int get_value() { return value; }  
  4. private:  
  5.     int value;  
  6. };  
class Test {public:    int get_value() { return value; }private:    int value;};

要求不用友元,不在这个类里添加任何代码,把成员变量k的值改为100,结果自然是通过公共成员函数get_value来验证。

 

“不在类里添加任何代码”,除了

  1. #define private public  
#define private public

我实在想不出其它的“偏门”方法了。那就想想不偏门的吧,论坛里好几位朋友提供了相当于如下代码的方法(为控制篇幅,本文中所有程序段都假设已包含了<iostream>头文件并引入了std名字空间,必要时还有其它头文件):

  1. Test t;  
  2. *(int*)&t = 100;  
  3. cout << t.get_value() << endl;  
Test t;*(int*)&t = 100;cout << t.get_value() << endl;

这种方式利用对象内存布局的特点:整个类只有一个整型成员,没有继承或虚拟继承,也没有任何虚函数,那么这个对象的地址也就是它的第一个成员变量的地址,所以只需要把对象地址强转成整型,那么获得的就是那个成员变量的地址,然后对转换后的地址再解引用,修改即可,在VC2003中验证,结果是正确的。

但指针的强制转换总给人带来不爽,不大安全的感觉,上面那条最关键的语句相当于:

  1. *reinterpret_cast<int*>(&t) = 100;  
*reinterpret_cast<int*>(&t) = 100;

也就是说,它动用了C++语言中最“强”的指针转换方式(说它最强,是因为没有什么指针之间他不能转换的)。其实我们完全可以做得更“文明”一点,方法是再定义一个联合体,比如:

  1. union TestInt {  
  2.     Test   t;  
  3.     int    i;  
  4. };  
union TestInt {    Test   t;    int    i;};

然后再:

  1. TestInt ti;    【联合定义时,只分配一个共享内存空间,不会进行任何初始化比如赋0等操作,其实联合类型的定义时就这样做了】
  2. ti.i = 100;  
  3. cout << ti.t.get_value() << endl;  
TestInt ti;ti.i = 100;cout << ti.t.get_value() << endl;

同样达到了目的,但实质上依据的机理跟上面的指针转换是一致的。

 

这个方法没啥大问题,就是有局限性,只能用于修改类的第一个成员,如果在value之前再加一个成员,比如:

  1. class Test {  
  2. public:  
  3.   
  4.     int get_value() { return value; }  
  5. private:  
  6.     char ch;  
  7.     int value;  
  8. };  
class Test {public:    int get_value() { return value; }private:    char ch;    int value;};

这种方法就不灵了。

当然,你可以手工算,认为char占一个字节,于是会试图取对象地址再加1得到成员value的地址。但第一,这种方法无法跨平台跨实现,char及int类型在不同的平台和编译器实现中的长度都可能是不一样的;第二,没有考虑字对齐问题,在内存中,value成员一般不会紧接着排布在ch之后,而是中间间开几个字节,最后将int类型对齐到另一个位置,比如4的倍数的地址上;而更糟糕的是,字对齐不仅跟平台相关,还跟预编译指令,甚至编译选项都会有关。所以,这种手工计算的方式还是放弃了吧。

有朋友提到了使用一种宏求出value成员相对于整个对象起始地址的偏移量,即定义一个宏:

  1. #define OFFSET(TYPE,MEM) ((int)(char*)&(((TYPE*)0)->MEM))  
#define OFFSET(TYPE,MEM) ((int)(char*)&(((TYPE*)0)->MEM))

这个宏通过把0地址转换为TYPE指针类型,然后从这个指针上“取”MEM成员,而MEM成员的地址转换后结果就是MEM成员相对于整个对象的偏移量(我们既然是从0地址开始算的,就不用再减去起始地址0)。

然后,我们通过使用这个宏作用于原来的类和目标字段,即: 

  1. OFFSET(Test, value)  
OFFSET(Test, value)

就可以获得value字段在Test类型对象中的偏移量,用对象的首地址加上这个偏移量,就可以得到value变量的地址,从而可以像上面一样解引用,修改。

这种方法不仅看起来难受,费解。事实上也根本行不通,因为这个宏所用到的技巧是从Test类型的指针上访问value成员——而valuee是private的!所以连编译都通不过。

论坛里有位朋友提出了另外一种方法可以巧妙地对付这个复杂一点的类,先做一个辅助类,它跟Test类很像,唯一的不同是它的成员都是public的:

  1. class TestTwin {  
  2. public:  
  3.     int get_value() { return value; }  
  4.   
  5. public:  
  6.     char ch;  
  7.     int value;  
  8. };  
class TestTwin {public:    int get_value() { return value; }public:    char ch;    int value;};

于是,这个TestTwin类跟原来的Test类在内存布局上不会有什么不同,通过指针转换,很容易借助于它来修改Test类对象的value成员:

  1. Test t;  
  2. TestTwin* p = reinterpret_cast<TestTwin*>(&t);  
  3. p->value = 100;  
  4. cout << t.get_value() << endl;  
Test t;TestTwin* p = reinterpret_cast<TestTwin*>(&t);p->value = 100;cout << t.get_value() << endl;

如果你不熟悉C++的显式指针转换方式:reinterpret_cast,在这里可以认为它相当于C风格的:

  1. TestTwin* p = (TestTwin*)&t;  
TestTwin* p = (TestTwin*)&t;

而前述的两条语句也可以合在一起,直接写成:

  1. reinterpret_cast<TestTwin*>(&t)->value = 100;  
reinterpret_cast<TestTwin*>(&t)->value = 100;

还有,厌恶指针操作的朋友仍可采用前面介绍的联合体方法来运用这个模具类,只是这次定义的联合体是这样:

  1. union TestTestTwin {  
  2.     Test       t;  
  3.     TestTwin   tw;  
  4. };  
union TestTestTwin {    Test       t;    TestTwin   tw;};

而程序是这样:

  1. TestTestTwin ttw;  
  2. ttw.tw.value = 100;  
  3. cout << ttw.t.get_value() << endl;  
TestTestTwin ttw;ttw.tw.value = 100;cout << ttw.t.get_value() << endl;

问题都解决了吗?如果类更复杂一些,会不会还有局限性呢?我们再把类改一改:

  1. class Test {  
  2. public:  
  3.     int get_value() { return value; }  
  4.     virtual ~Test() {}  
  5. private:  
  6.     char ch;  
  7.     int value;  
  8. public:  
  9.     int a;  
  10.     double b;  
  11. protected:  
  12.     string e;  
  13. private:  
  14.     short d;   
  15. };  
class Test {public:    int get_value() { return value; }    virtual ~Test() {}private:    char ch;    int value;public:    int a;    double b;protected:    string e;private:    short d; };

这次不仅成员多了许多,有string类型的成员(须include <string>),还弄出个虚析构函数来(我们都知道拥有虚函数的类会导致其实例中多一个虚表指针)。但后面会看到,虚函数对我们讨论的问题影响不大,我们加上它只是想证明:只要方法足够好,不怕对象更复杂。

那上面的模具办法问题出在哪里呢?为什么不能同样再搞一个类,把那个value改为public的,然后用它来“套住”原来对象中value成员呢?

原因是C++语言只保证类中同一个access section(即从一个访问权限修饰符public/private/protected到另一个修饰符之间的部分)中定义的非静态成员变量会按照声明时的顺序分布的内存中,但并不保证跨越了不同access section的所有成员变量都在内存中按声明时的顺序存放,某种编译器完全有可能把所有的private块都合成一块,甚至整个给扔到所有protected成员的后边去(虽然VC并没这么做)。

换句话说:改掉了一个成员的访问权限,就可能改变了对象的内存布局。于是,改变了的模子也就不再能够套住相应位置上的成员。

但办法还是有,只需要将原来的改进一下:

在现有的C++对象模型中,为类增加一个非虚成员函数,不会改变对象的内存布局,我们可以利用这一点来写一个TestTwin:

  1. class TestTwin {  
  2. public:  
  3.     int get_value() { return value; }  
  4.     void set_value(int v) { value = v; }  
  5.     virtual ~TestTwin() {}  
  6.   
  7. private:  
  8.     char ch;  
  9.     int value;  
  10. public:  
  11.     int a;  
  12.     double b;  
  13. protected:  
  14.     float e;  
  15. private:  
  16.     short d;   
  17. };  
class TestTwin {public:    int get_value() { return value; }    void set_value(int v) { value = v; }    virtual ~TestTwin() {}private:    char ch;    int value;public:    int a;    double b;protected:    float e;private:    short d; };

这个模具跟原来的Test类也是只有一点不同:增加了一个公共的,非虚的set_value方法,用来给私有成员value赋值。于是,程序可以这么写:

  1. Test t;  
  2. reinterpret_cast<TestTwin*>(&t)->set_value(100);  
  3. cout << t.get_value() << endl;  
Test t;reinterpret_cast<TestTwin*>(&t)->set_value(100);cout << t.get_value() << endl;

验证通过。

增加的虚函数纯粹是个障眼物而已,它跟我们采用的方法几乎没有丝毫联系,所以也就丝毫不用担心虚函数对内存分布的影响会影响到这个方法的正确性。但被它一搞,那个使用联合体的方法这一次还真是不管用了,因为有了析构函数的类不能再放进联合体中了——否则当联合体实例的生命周期结束时,析构谁呢?

 

想了半天,能想到的只有这么多了。

最后,不得不承认,“增加一个非虚成员函数,不会改变对象的内存布局”这句话也无法从C++标准中得到直接支持,只是对于目前大多数编译器来说,这都是没问题的。因为这种“让类的每个实例拥有一份独立的成员变量,而类的所有实例共享一份成员函数”的C++对象模型是C++之父Bjarne Stroustrup先生本人所提出的,其时间、空间效率都很好地符合了C++语言的设计初衷,不仅现代C++编译器没有不这么做的,就连Java/C#编译器也都这么做。所以,也算是个“相对真理”了。

PostgreSQL 超详细安装与使用教程:从入门到实战 本文将详细介绍PostgreSQL数据库的安装配置与基础使用。首先从Windows系统安装入手,分步骤讲解17.5版本的安装流程、环境变量配置及服务启动验证。接着重点介绍了pgAdmin4图形化管理工具的安装与使用,包括界面语言设置、数据库连接、创建与管理数据库等操作,同时对比了可视化操作与SQL命令两种方式。最后梳理了PgSQL基础语法,涵盖表的创建、增删改查操作、约束管理等内容,为初学者提供了完整的PostgreSQL入门指南。文章兼顾理论知识与实际操作,既适合数据库新手学习,也可作为开发人员的快速参考 阅读详情

相关推荐

Python RPA 流程自动化快速上手

Python RPA 流程自动化快速上手

看花容易绣花难 1万+

从一个修改私有变量的问题想到的

前几天,在论坛里看到一个帖子,内容是:(原帖见:http://community.youkuaiyun.com/Expert/topic/5014/5014384.xml?temp=.3018152)========================================class a{private:int k;};要求不用友元,不在这个类里添加任何代码,去访问成员变量k。能做出的高手,请贴出完整源

小三的学习园地 978

[模型部署]-[LLM]昇腾部署Qwen3-Coder-30B-A3B-Instruct

摘要:本文介绍了在Ascend NPU上部署Qwen3-Coder-30B-A3B-Instruct大模型的实践过程。通过vLLM-Ascend框架,详细说明了环境准备(CANN 8.1、PyTorch-NPU 2.5.1等)、模型下载、容器启动及服务部署步骤,包括vLLM服务的启动参数配置和接口测试方法。测试结果显示在当前2卡910B3配置下性能表现仅为8token/s(1并发),并指出流式调用时存在无法输出usage信息的问题。该方案为Ascend平台私有化部署大模型推理服务提供了参考实现。

1668

如何在不修改类成员属性的情况下,访问类的私有成员?

成员函数、友元类,友元函数,甚至通过指针。 通过内存地址直接去访问private只在编译时有效,编译后class被处理成一个结构运行并没有额外的机制去检查成员的访问权限。 最常用的方法应该是增加公共成员函数去访问,这是最容易想到的,这是标准做法,满足c++的封装特性; 高级做法用友元类和友元方法; 牛人做法用指针内存访问读取(类指针+地址偏移量),但是使用这种方式容易导致很多野指针的问题。 ...

Clement 626

Cheat Engine实战:多级指针逆向破解游戏内存的5个关键步骤(附C++模拟代码)

本文详细解析了使用Cheat Engine进行多级指针逆向破解游戏内存的完整流程。通过5个关键步骤,从定位动态地址到逐层追踪指针链,最终构建稳定指针路径。文章结合C++模拟代码,深入剖析了指针链的底层汇编原理,并提供了高级排查技巧,帮助读者掌握逆向工程中的核心内存追踪技术。

weixin_29239279的博客 306

带隙基准电路设计实战:从HSPICE仿真到Virtuoso版图全流程解析

在模拟集成电路设计中,基准电压源是确保系统精度与稳定性的核心模块。其基本原理在于巧妙结合具有正、负温度系数的电压,通过加权求和实现近似零温度系数的稳定输出,这一特性对于高精度数据转换器、电源管理芯片等至关重要。从工程实践角度,利用HSPICE进行深入的直流工作点、温度扫描和工艺角仿真,是验证电路性能、优化温度系数和电源抑制比的关键步骤。而借助Cadence Virtuoso进行版图实现时,必须重点关注电阻与BJT的匹配布局、敏感节点的保护以及电源完整性设计,以确保设计意图在硅片上得以准确呈现。通过完整的从前

weixin_29181861的博客 284

vc如何动态增加类的成员函数

<br />struct   someClass; <br />typedef   LPVOID   (*pfCallback)(someClass*   pThis,LPVOID); <br />struct   someClass{ <br /> static CONST int   m_xxx=0; <br /> CArray <pfCallback>       m_arr_pCallback; <br /> LPVOID   invoke(int   idx,LPVOID   parm); <br

kafeiwuzhuren的专栏 1897

高效获取Sentinel-2影像:哥白尼数据中心下载全流程解析

本文提供了一份从哥白尼数据中心高效下载Sentinel-2卫星影像的保姆级指南。详细解析了从账号注册、使用Copernicus Browser界面、精准划定研究区域,到利用云量覆盖、时间范围等关键条件筛选L2A地表反射率产品的全流程,旨在帮助用户快速获取高质量遥感数据,避免常见错误。

weixin_29247219的博客 255

c++17 获取类私有变量(不改变原有类结构)

/ADL 创建myclass后 dosomething可以不用显示声明命名空间。//基于模板 不需要friend方式。//下面是上述模板原理,成员指针。//不声明获取类私有变量。//外部类声明friend。

tlglove326的博客 688

在 SAP SD(销售与分销)模块中,销售合同 / 订单的抬头(Header) 和行项目(Item) 核心数据表如下,按 “核心表 + 扩展表” 分类说明,同时区分销售合同(Contract,类型 W

SAP SD模块中销售合同/订单的核心数据表分为抬头和行项目两类。核心抬头表包括VBAK(基础数据)和VBUK(状态数据),核心行项目表包括VBAP(基础数据)和VBUP(状态数据)。扩展表包含VBAKE(抬头增强)、VBAPe(行项增强)、VBEP(计划行)、VBFA(凭证流)等。销售合同(WK/WC)和订单(OR)通过VBAK-AUART字段区分,核心表结构相同。查询时需注意单据类型筛选,并通过VBELN主键关联抬头和行项数据,KNUMV关联定价条件,VBFA表追踪凭证流。

金牌架构师 1090

计算机组成原理(第三版)唐朔飞-第五章输入输出系统-课后习题

计算机组成原理(第三版)唐朔飞-第五章输入输出系统-课后习题

weixin_45735391的博客 6万+

【C/C++】类成员函数地址的获取及使用方法

#include using namespace std; class A { public: A() : a(910){}; void foo1(int i) { cout << "hello, foo1" << endl;} void foo2(int i) { cout << "hello, foo2\t" << a << endl;} private: int a; };

Data spark in Pypot 1752

从你的全世界路过---陌陌X-SIGN还原

我们上期介绍了hook 接口方式,今天我分析so 层。学习是为了复杂的事情简单化。不用如此繁琐。跟进native_sdbyecbu37x这个函数,我们f5看伪代码 v13 = sign(v9, v10, v11, a6); 跟进这个函数 代码如下(示例): 2.代码贴入 SHA消息摘要java代码如下: java 代码如下(示例): 总结 算法,结合动态调试!

任雪飘的博客 2299

c++中类外访问一个类的私有成员

正常来说,类外无法访问类内的private成员,只能通过类内成员访问private成员,在类外,无论是通过类指针还是类对象都无法直接访问类中的private成员 C++类中的私友成员是不能通指针操作的。 #include <iostream> using namespace std; class A { int a;//private public : int b;//publ...

chengchaonan的博客 9145

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

C++ 语言类的私有成员

C++ 语言类的私有成员 1. 类的私有成员 构造函数是为类对象的数据成员赋值的。 在定义类成员时使用关键字 private,可以得到所需的安全性。通常情况下,私有类成员只能被类的成员函数访问,有一种情况例外。普通的函数没有访问私有类成员的直接途径。 指定私有类成员能够将类的接口与类的内部实现分开。类的接口由 public 成员和 public 函数成员组成,在必要时,public 函数成员可以提供对包括 private 成员在内的所有类成员的间接访问。例如,将类的内部成员指定为 private,就可以修

程永强 8967

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

通过指向的指针访问C++类的私有成员

通过指向的指针访问C++类的私有成员 C++对象的私有成员是禁止类外的访问的。但是我们仍然可以通过指针访问C++对象的私有成员。 #include <iostream> using namespace std; class A { public: A(int i = 0) :m_i(i) {} void print() { cout << "m_i" << this->m_i << end

qq_43780332的博客 2424

C++访问类中私有成员变量的方法

原则上,C++类中私有变量不允许在类之外的其他任何地方访问,一般来说功能完善的类都会提供get,set方法来操作类属性值,还有就是就是通过友元访问。但是!但如果没有get、set方法都没有提供,也没有定义友元,比如使用的是第三方提供的.o(或者动态库)来进行开发的,并且实际应用中我们确确实实需要改变其中某个对象的一个私有参数,有没有什么办法呢?还有一种比较文艺青年的方法,我们知道,一个进程有程序段

小熊不去实验室 1万+

c++访问类中私有成员变量的几种方法

今天突然遇到这个需求了,就拿出来记录一下。 常用的3种方法 set/get接口 友元类/友元函数 通过指针访问内存地址 1.友元方法 #include<iostream> using namespace std; class A { public: A(){} ~A(){} friend class B; //声明友元类 private: int num = 10; } class B { public: A a; int Sum(){ return a.num + 10

初心不改 1万+

C++ 访问其他类私有成员的两种方式

最近在用Qt写一个CT三维可视化的软件,需要在对话框类中访问主窗口类中成员函数与变量。主窗口中声明的成员变量和核心功能的成员函数均为私有成员,那么在对话框类中访问它们则可以使用包含但不仅限于(C++博大精深,不敢把话说满)以下的两种方法: 在主窗口类中创建公有成员函数,通过在类中获取私有成员来供其他类对其进行访问及修改: class A{ public: int* getNum(){ return &num; } private: i

weixin_41085521的博客 4656

C/C++—— 除了用类成员函数访问类私有成员变量外,还可以通过类对象地址来直接访问和修改类的私有成员变量

除了用类成员函数访问类私有成员变量外,还可以通过类对象地址来直接访问和修改类的私有成员变量

Be The Best! 1952

C++中直接存取类私有成员

 本文谈到的问题是,在C++中究竟有没有办法访问类的私有成员,以及如何实现。主要针对菜鸟,老鸟们就不要看了。 读到《C++编程思想》48页,“3.4 对象布局”一节时,看到这样一段话:  存取指定符是struct的一部分,他并不影响这个struct产生的对象,程序开始运行时,所有的存取指定信息都消失了。存取指定信息通常是在编译期间消失的。在程序运行期间,对象变成了一个存储区域,别无他物,因此,

Hakuna Matata 3904

C++ 类外访问类的私有成员变量

C++ 类外访问类的私有成员变量 之前一直不太清楚对象的成员变量和成员函数在内存中的占用情况,今天想要直接通过一个对象的变量名去访问其内部的成员变量,特地去看了一下对象中的内存布局。 直接说结论: 对于没有继承的情况,对象所占内存的大小和C结构体类似,仅需考虑内存对齐+每个基本成员变量的内存大小就计算出对象所占内存。 对于有继承的情况,如果有虚函数,那么除了基本的成员变量外还会存储一个虚表指针,这个指针的位置可能在这个对象的内存的头部也可能在尾部,这个视编译器而定。派生类对象的内存大小会是父类大小加上自身

man_skill的博客 2780

c++ 访问和修改类的私有变量

模板显式实例化(template Explicit instantiation) 我们知道, 对于类模板来说, 我们提供模板参数可以实例化一个模板类. 除了这种方法以外, 模板还可以使用显式实例化, 在显式实例化的时候, 会忽略参数的private属性. 所以到此, 访问的方法就比较清晰了. 我们可以定义一个指针来指向类的私有成员, 但是由于成员是私有的, 直接赋值不会成功, 所以我们可以利用模板...

xiangxianghehe的博客 3994

C++---父类中的私有成员可以通过地址访问吗?

我们知道,私有变量在类外是不可访问的,并且父类的私有成员在子类也是不可访问的,但是我们不知道是什么原因,是编译器真真正正的做了手脚,还是只是简单的限制。我们来研究一下。 问题一:类里面的私有成员能否通过具体的地址来访问? 问题二:父类被继承到子类之后,父类的成员变量是根本就没有继承下来,还是确实继承下来,只是简单的进行了访问的限制? 我们举例子来验证: #include<iostream&g...

shanghx_123的博客 824

B类对象访问A类中的私有成员

综上三种方式,方式一是最好最简单的方法,也应该是最容易想到的,通过公有成员函数访问私有成员并暴露接口给其他类,符合类的私有成员设计初衷,保护了数据。现在想来,面试官其实最想听到的是这个答案吧。

HL_LOVE_C的博客 736

如何强制访问c++私有成员

出自:http://blog.sina.com.cn/s/blog_01d05ff50100no9q.html 前几天笔试adobe,出了这样一个题,当时只想到通过指针的偏移量来访问,但是由于对C++的类对象布局不是很有把握,就随便写了个答案,今天上百度搜了下,发现好几种方法,拿出来一起分享。   先看一个类   #include     class A   {

YYC的专栏 1501

不用友元访问类私有成员 X C++对象模型

   虽然没有现实意义,但对理解C++的对象模型是很有帮助的。    前几天,在论坛里看到一个帖子,内容是:     (原帖见:http://community.youkuaiyun.com/Expert/topic/5014/5014384.xml?temp=.3018152)     ========================================     class   a     {

boluo1982107的专栏 1132
上一篇: c++高级---C_C++的union的学习笔记总结
下一篇: 错误纠正--内存布局问题
HNFXS985
博客等级 码龄14年 219粉丝 150原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值