C + + breaking through the black technology of private access

Posted by wisedj on Tue, 03 Dec 2019 22:29:32 +0100

How to break through the private attribute limit of class -- trying to break the encapsulation of class, a little "against the sky" feeling.

Method 1. Add friend function

#include<iostream>
using namespace std;

class X
{
private:
	int m_Age;

public:
	X() : m_Age(1){}

	template<typename T>
	void Func(const T &t){}

	const int GetValue()
	{
		return m_Age;
	}

	friend void Func(X* xPtr);
};


void Func(X* xPtr)
{
	xPtr->m_Age = 2;
}

int main() {
	X x;
	cout << x.GetValue() << endl;// Output 1

	Func(&x);
	cout << x.GetValue() << endl;// Output 2

	getchar();
	return 0;
}

Using friend functions should be the first solution to come up with.

A friend function of a class is defined outside the class, but has access to all private and protected members of the class.

Method 2. Use pointer type conversion to steal the day

#include<iostream>
using namespace std;

class X
{
private:
	int m_Age;

public:
	X()	: m_Age(1){}

	template<typename T>
	void Func(const T &t){}

	const int GetValue()
	{
		return m_Age;
	}
};

// Same as the memory layout of X, change the type definition of variable to public
class Y
{
public:
	int m_Age;
};

void Func(X* xPtr)
{
	// Reinterpret? Cast is used to carry out the
	// Conversion between references of different types and between pointers and integer types that can hold pointers.
	(reinterpret_cast<Y*>(xPtr))->m_Age = 2;
}

int main() {
	X x;
	cout << x.GetValue() << endl;// Output 1

	Func(&x);
	cout << x.GetValue() << endl;// Output 2

	getchar();
	return 0;
}

First of all, we convert X-type pointer to Y-type pointer. In the view of compiler, we are accessing the public member m'age of Y-type, so the compilation passed. However, in fact, the pointer is X-type. Because the memory layout of Y and X is exactly the same, the m'age member accessing y is actually accessing the m'age member of X.

For the memory layout of the class, you can see here: https://blog.csdn.net/qq826364410/article/details/88917375

Method 3: using template to drill holes

If there is a member template in X, it can look like this:

#include<iostream>
using namespace std;

class X
{
private:
	int m_Age;

public:
	X() : m_Age(1){}

	template<typename T>
	void Func(const T &t){}

	const int GetValue()
	{
		return m_Age;
	}
};

struct Y {};

template<>
void X::Func(const Y&) //Specialization
{
	m_Age = 2;
}

int main() {
	X x;
	cout << x.GetValue() << endl;// Output 1

	x.Func(Y());
	cout << x.GetValue() << endl;// Output 2

	getchar();
	return 0;
}

This method takes advantage of the fact that X has a member template, and penetrates the enemy's interior through the specialization function template. The code is fully compliant with the standard, which also ensures that this behavior will follow the intentions of the coder. boost and loki use this technique extensively.

Topics: Attribute