profile
engineer . tinkerer . father

Andreas Heimberger

  • home
  • github
  • instagram
  • xing
  • linkedin
Built with Hugo

Fool Me - Private Member Access In C++

I’ve come across similar practices in various projects. While I admire people’s proficiency in leveraging language features to accomplish tasks, there are times when I find myself wondering, why? Even though languages offer these ‘clever’ features, I believe it’s crucial to maintain simplicity in a language and question why it doesn’t implement a proper Getter and Setter. Code will be added, lines will become more and more. The knowledge of an implementation is lost over time and sooner or later those ‘clever’ workarounds unfortunately will lead to unexpected behavior.

Here are some nasty things, I have seen so far:

#include <iostream>

// Bang: Hold onto your hats! It's the 'private' magic trick!
#define private public

class T {
private:
	int x{20};
};

int main() {
	T t;
	std::cout << t.x << std::endl;
}
#include <iostream>

class Test {
private:
	int x{20};
	friend class TestClass;
};

// Bang: Friends don't always make the best companions!
class TestClass {
public:
	int X(const Test &test) { return test.x; }
};

int main() {
	Test test;
	TestClass testClass;
	std::cout << testClass.X(test) << std::endl;
}
#include <iostream>

class Test {
private:
	int data{20};

public:
	void print() { std::cout << data << std::endl; }
};

int main() {
	Test t;
	t.print();
	// Bang: And now the grand finale, casting to the underworld!
	int* ptr = (int*)&t;
	*ptr = 100;
	t.print();
}

In my opinion, if a situation arises where someone needs to access a class’s member variable for setting or getting purposes, it’s preferable to implement specific methods for it. Even if this entails adding an extra method, it enables better tooling support ( right click - find references ;) ) to identify the usage and behavior of the function. In contrast, other approaches may provide less visibility into how the variable has been modified.

#include <iostream>

class Test {
private:
	int data{20};

public:
	int getData() const { return data; }
};

int main() {
	Test t;
	std::cout << t.getData();
}

So, my fellow code explorer, let us remember the importance of simplicity, the power of proper access methods, and the perils of clever workarounds. Happy coding adventures! 🚀