c++访问私有private成员变量的常用方法

所属分类: 软件编程 / C 语言 阅读数: 70
收藏 0 赞 0 分享

类的对象不能直接访问类声明的私有成员变量,否则破坏了信息隐藏的目的。

在C++中,为了防止某些数据成员或成员函数从外部被直接访问,可以将它们声明为private,这样编译器会阻止任何来自外部非友元的直接访问。

私有成员变量的常用访问方法如下:

(1)通过公共函数为私有成员赋值

#include <iostream> 
using namespace std; 
 
class Test 
{ 
private: 
	int x, y; 
public: 
	void setX(int a) 
	{ 
		x=a; 
	} 
	void setY(int b) 
	{ 
		y=b; 
	} 
	void print(void) 
	{ 
		cout<<"x="<<x<<'\t'<<"y="<<y<<endl; 
	} 
} ; 
 
int main() 
{ 
	Test p1; 
	p1.setX(1); 
	p1.setY(9); 
	p1.print( ); 
	return 0; 
} 

(2)利用指针访问私有数据成员

#include <iostream> 
using namespace std; 
class Test 
{ 
private: 
	int x,y; 
public: 
	void setX(int a) 
	{ 
		x=a; 
	} 
	void setY(int b) 
	{ 
		y=b; 
	} 
	void getXY(int *px, int *py) 
	{ 
		*px=x; //提取x,y值 
		*py=y; 
	} 
}; 
int main() 
{ 
	Test p1; 
	p1.setX(1); 
	p1.setY(9); 
	int a,b; 
	p1.getXY(&a,&b); //将 a=x, b=y 
	cout<<a<<'\t'<<b<<endl; 
	return 0; 
} 

(3)利用函数访问私有数据成员

#include <iostream> 
using namespace std; 
class Test 
{ 
private: 
	int x,y; 
public: 
	void setX(int a) 
	{ 
		x=a; 
	} 
	void setY(int b) 
	{ 
		y=b; 
	} 
	int getX(void) 
	{ 
		return x; //返回x值 
	} 
	int getY(void) 
	{ 
		return y; //返回y值 
	} 
}; 
int main() 
{ 
	Test p1; 
	p1.setX(1); 
	p1.setY(9); 
	int a,b; 
	a=p1.getX( ); 
	b=p1.getY(); 
	cout<<a<<'\t'<<b<<endl; 
	return 0; 
} 

(4)利用引用访问私有数据成员

#include <iostream> 
using namespace std; 
class Test 
{ 
private: 
	int x,y; 
public: 
	void setX(int a) 
	{ 
		x=a; 
	} 
	void setY(int b) 
	{ 
		y=b; 
	} 
	void getXY(int &px, int &py) //引用 
	{ 
		px=x; //提取x,y值 
		py=y; 
	} 
}; 
int main() 
{ 
	Test p1,p2; 
	p1.setX(1); 
	p1.setY(9); 
	int a,b; 
	p1.getXY(a, b); //将 a=x, b=y 
	cout<<a<<'\t'<<b<<endl; 
	return 0; 
}

下面是其它网友的补充

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

原则上,C++类中私有变量不允许在类之外的其他任何地方访问,一般来说功能完善的类都会提供get,set方法来操作类属性值,但如果没有get、set方法都没有提供,比如使用的是第三方提供的.o(或者动态库)来进行开发的,并且实际应用中我们确确实实需要改变其中某个对象的一个私有参数,有没有什么办法呢?我们知道,一个进程有程序段和数据段,如果我们知道了对象的数据空间,那么得到该对象的成员变量值也就很简单了,而实际上,对象数据段的首地址其实就是对象地址,以例子说明:

class A
{
public:
 int i;
 bool setJ(int _j){j = _j;};
 int getJ() const {return j;};
private:
 int j;
};

int main()
{
 A a;
 printf("a's address is %u.n",&a); // 打印对象a的地址
 printf("a.i's address is %u.n",(&(a.i))); // 打印对象a的成员变量i的地址
}

执行上面程序,可以看到结果,两个值时一样的,也就是说明对象地址就是第一个成员变量的地址。
我们知道,C++编译器将数据和程序段分开,所有的类变量会按照声明顺序依次存入数据段,所以,如果知道了第一个变量的地址,那么后面的地址也就依次累加即可逐一求出了。有了变量地址,那么也就可以对它的值进行修改了。还是以上面的例子来说明,一下程序编写了如何更改类成员b的值:

int main()
{
 A a;
 a.setJ(2);
 printf("before modified:the member j of a is %d.n",a.getJ()); // 打印j的值。
 int *p = (int *)(int(&a) + sizeof(a.i));
 *p = 10;
 printf("after modified:the member j of a is %d.n",a.getJ()); // 打印j的值。
}

可以得出此时j成员变量的值由2变成10了。

总结:直接对地址空间操作,请小心为妙。。。 

此外,另附一篇与此类似的文章,也很有启发性。

分析程序员和黑客的区别

 题目:
  设有如下C++类

class A
{
 int value;
public:
 A(int n = 0) : value(n) {}
 int GetValue()
 {
 return value;
 }
};

请使用某种方式来在类的外部改变私有成员A::value的值。

程序员的可能做法:

class A
{
 int value;
public:
 A(int n = 0) : value(n) {}
 int GetValue()
 {
 return value;
 }
 void SetValue(int n)
 {
 value = n;
 }
};
void f()
{
 A a;
 a.SetValue(5);
}

黑客的可能做法:

void f()
{
 A a;
 *((int *)&a) = 5;
}

结论:

程序员习惯于遵循既有的限制来增加既有的东西。
黑客习惯于利用既有的东西来打破既有的限制。

更多精彩内容其他人还在看

C++无法重载点符号、::、sizeof等的原因

这篇文章主要介绍了C++无法重载点符号、::、sizeof等的原因的相关资料,需要的朋友可以参考下
收藏 0 赞 0 分享

实例讲解C语言编程中的结构体对齐

这篇文章主要介绍了C语言编程中的结构体对齐,值得注意的是一些结构体对齐的例子在不同编译器下结果可能会不同,需要的朋友可以参考下
收藏 0 赞 0 分享

详解C语言的结构体中成员变量偏移问题

这篇文章主要介绍了C语言的结构体中成员变量偏移问题,以讲解如何编写宏来对成员变量进行修改为主,需要的朋友可以参考下
收藏 0 赞 0 分享

详解C语言结构体中的函数指针

这篇文章主要介绍了详解C语言结构体中的函数指针,文中对函数指针的基本概念也有讲解,需要的朋友可以参考下
收藏 0 赞 0 分享

C++编程中的函数指针初步解析

这篇文章主要介绍了C++编程中的函数指针初步解析,函数指针在C语言和C++学习中都是非常重要的知识,需要的朋友可以参考下
收藏 0 赞 0 分享

实例解析C++中类的成员函数指针

这篇文章主要介绍了C++中类的成员函数指针,例子中以讨论用函数指针调用类的成员函数为主,需要的朋友可以参考下
收藏 0 赞 0 分享

C语言中的函数指针基础学习教程

这篇文章主要介绍了C语言中的函数指针基础学习教程,包括函数指针作为参数来传递等重要知识,需要的朋友可以参考下
收藏 0 赞 0 分享

深入解析C语言中函数指针的定义与使用

这篇文章主要介绍了C语言中函数指针的定义与使用,是C语言入门学习中的基础知识,需要的朋友可以参考下
收藏 0 赞 0 分享

详解C语言编程中的函数指针以及函数回调

这篇文章主要介绍了C语言编程中的函数指针以及函数回调,函数回调实际上就是让函数指针作函数参数、调用时传入函数地址,需要的朋友可以参考下
收藏 0 赞 0 分享

C语言中的函数指针学习笔记

这篇文章主要介绍了C语言中的函数指针的一些学习知识点记录,文中作者整理了一些比较interesting的函数指针用法,需要的朋友可以参考下
收藏 0 赞 0 分享
查看更多