What's your take on protected variables?

Started by
26 comments, last by Codarki 11 years, 5 months ago
What's your take on protected variables?

In the context of c++, it seems most experts (Scott Meyes, Herb Sutter) think is not a good idea. I don't agree. In fact, some languages, for example Ruby, have only automatic protected variables.
It seems silly to make a 'setter' and 'getter' functions for a variable when the derived object is employ in terms of "is-a". Also, making 'setter' functions opens the variable to be manipulated from outside the object! Of course, one could make in the 'setter' protected, but isn't that 'running in a loop'?

Please, discuss.

EDIT:

Let's say I have:

[source lang="cpp"]
class Shape{
public:
virtual void CalculateArea();
private: //private!
int x, y;
int width, height;
};

class Rectangle : public Shape{
public:
void CalculateArea(){
/* I need width and height to calculate, but can't access it.
What can I do? */
}
};
[/source]
If I make 'getters' for Shape class:

[source lang="cpp"]
class Rectangle : public Shape{
public:
void CalculateArea(){
get_width(); //isn't this silly, as width is a fundamental part of Rectangle
//also, now everyone knows my width!
}
};
[/source]
Advertisement
Protected variables pose some of the same problems public variables do, they expose parts of their class' internal state which can lead to an invalid class state.
If you create a protected variable inside a class each subclass will be able to do anything it wants with that variable, which means the original base class will not be able to check whether this variable remains valid against its class invariant. This of course leads to a class which is much harder to test, and you will probably have a much harder time proving the correctness of that class.

Using an accessor-mutator pair (even if these are protected) inside your base class allows it to do checks on the variable so the class remains valid at all times.

I gets all your texture budgets!

I never use protected in my code. I find that public and private are expressive enough: I either want this to be part of the interface or a detail of implementation, and I don't feel the need to have derived classes have special privileges. On the other hand, I don't use inheritance all that often, so perhaps protected makes more sense in other styles of coding than my own.

It seems silly to make a 'setter' and 'getter' functions for a variable when the derived object is employ in terms of "is-a". Also, making 'setter' functions opens the variable to be manipulated from outside the object! Of course, one could make in the 'setter' protected, but isn't that 'running in a loop'?

1) If you automatically make getters and setters for every non-public variable then you're doing OOP wrong. 2) Protected member functions don't have the same issues that protected member variables do. As long as your protected member functions maintain class invariants, derived classes can't use them to violate class invariants the same way they could with raw access to protected variables.
TODAY... Generally protected variables are a bad idea. Protected functions are great, though, especially protected mutators. They provide a choke point to ensure all usage is correct. There is a tiny performance overhead, on modern CPUs that overhead is measured in the nanoseconds and is usually unimportant.

In 1980's and early 1990's... Protected variables were one of the best costing solutions to a real problem. They could be used with several design patterns (although they weren't named that, yet) to allow base class functionality to be modified by child classes. Since the compiler optimizers were not that great, having a protected variable meant just a single move instruction whereas mutators and accessors would require multiple jumps and generally hurt performance.


I can imagine some creative folks coming up with problems today where protected variables are a good idea, or at least better than the normal alternatives.
Inheritance hierarchies (as opposed to inheritance only of interfaces) is a bit of a blunt instrument to start with. I'm generally pretty distasteful of any design that requires inheritance more than a single level in depth.

But basic inheritance is just hierarchical adaptation of functionality, and that I can, for the most part, live with. Protected instance variables, on the other hand, allow hierarchical mutation of state. And that is just... ugly. Can't think of a better word for it.

The only reasons to put state in a class in the first place, is if you either need to enforce constraints on the value of that state, or take action based on changes to that state. Protected instance variables violate both of those reasons, since the state may be modified without the knowledge of the super-class.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]


Since the compiler optimizers were not that great, having a protected variable meant just a single move instruction whereas mutators and accessors would require multiple jumps and generally hurt performance.


As always, the world has gone full circle :

http://developer.android.com/guide/practices/performance.html

Google are advocating that programmers should access class field directly, because the Android platform's compiler, at least for now, can't inline acessor/mutator calls.
[source lang="cpp"]
class Shape {
public:
virtual void CalculateArea() = 0;
private: //private!
int x, y;
int width, height;
};

class Circle : public Shape {
public:
void CalculateArea() {
/* Even if my privates were protected, I'd be in trouble. */
}
};
[/source]

Maybe the answer is proper design.

Stephen M. Webb
Professional Free Software Developer

The only time I feel protected members are useful, is with protected functions, as others said (ignoring any performance concerns). Even further, I feel the only functions which should *maybe* be protected, are virtual functions. Any member variable should be private or public. Any non-virtual function should be private or public. Even most virtual functions should be public... but sometimes it's nice to hide them, to not bloat the interface.

A Ctrl+F of the keyword 'protected' in my code base of 209 classes (50k lines of code) finds only two uses of "protected", and both are for a single virtual function in each class (and both are overriding a Qt base-class function. Hmm, odd).

[size=2](It also found a single use of 'goto' =P)
[size=2](It also found a single use of 'goto' =P)


Was it "//goto store - buy burritos"? biggrin.png

I don't really understand the downside of protected variables. Yeah, you can create a subclass and then access the protected members, but that's only for instances of your derived class.

I mean it just sort of strikes me as the same as the "Do not attempt to stop chainsaw with hands or genitals." sticker.

You can only help people so much. After that they're kind of on their own. If someone wants to use inheritance to abuse a class then they're only hurting themselves, aren't they?

That being said, I usually only use inheritance for polymorphism and use virtual base classes, so maybe I don't know what I'm talking about.
void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.

This topic is closed to new replies.

Advertisement