By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
443,836 Members | 2,059 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 443,836 IT Pros & Developers. It's quick & easy.

Protected Static may as well be public?

P: n/a
I just made an observation and I wondered if it's generally known (or
if I'm missing something). My observation is that static protected
members are essentially useless, only a hint to the user. They don't
actually protect any encapsulation or anything, and for all the actual
protection they offer, they might as well be public.

For example:

class B {
protected:
static int i;
static void f();
};

int B::i=0;
void f() {
}

Nothing stops anybody anywhere from reading or changing B::i or from
calling B::f(). All anyone needs to do is create a derived class like
so:

struct D : B {
static int &i() { return B::i; }
static void f() { B::f(); }
};

And, voila, the static protected method is (indirectly) publicly
accessible. Two lines of code overhead plus a line for each member to
be exposed. No one even has to create an instance, so private
constructors and destructors are no protection either.

Is this generally known (and is it correct)? Maybe people seldom make
protected static members, so it's rarely an issue in practice.

Aug 25 '05 #1
Share this Question
Share on Google+
13 Replies


P: n/a
seems like you are misinterpreting the scecurity access provided by the
c++ language!!!

c++ dosn't offer you the scecurity in the sense of the one provided by
some encryption algorithm that can withstand your malicious attempts as
well. c++ just gives you access specifier so that if you want to create
good software you can create that. however if you
want to misuse the access specifiers u can do that as well.

though nothing special about this static members case only. the same
sceurtiy can
be bypasses if you have protected member in base class and some derived
class function returns gives access to these protected memeber objects
by exposing some public functions for this.

thanks
rt

Aug 25 '05 #2

P: n/a
ra************@gmail.com wrote:
c++ dosn't offer you the scecurity in the sense of the one provided by
some encryption algorithm that can withstand your malicious attempts as
well. c++ just gives you access specifier so that if you want to create
good software you can create that.
I understand that. But in most other cases, you have to do something
crafty like a weird cast or a preprocessor hack that probably invokes
UB to break encapsulation (assuming the class is otherwise well
designed). In this case, access is achieved using fairly basic
language features.
however if you
want to misuse the access specifiers u can do that as well.
Well, more to the point, considering how easy this is, what kind of
protection are you asking for when you make a protected static member?
It's rather easy for access to leak out to just about anyone even if
you discard malicious intent.

When I make a member function protected, I have the assurance that only
derived classes will be able to invoke it, and then only on themselves
or instances of their own class. I see no similar assurance given by
"protected static" to anyone anywhere.
though nothing special about this static members case only. the same
sceurtiy can
be bypasses if you have protected member in base class and some derived
class function returns gives access to these protected memeber objects
by exposing some public functions for this.


True, but in this case only instances of the poorly designed class are
exposed. Any other class inheriting from B will still be fully
protected. And instances of B itself are fully protected.

Aug 25 '05 #3

P: n/a
Adam H. Peterson wrote:
<snip>
I understand that.**But*in*most*other*cases,*you*have*to
do*something crafty like a weird cast or a preprocessor
hack that probably invokes UB to break encapsulation
(assuming the class is otherwise well designed).**In
this*case,*access*is*achieved*using*fairly*basic
language features.

<snip>

You can promote all protected members (data and methods,
both static and non-static) to public in derived classes,
so you can as well claim that all protected members could
as well be public. What's more, you can give access to
any private data or member if you really try:

class Leaking {
int i;
void f();
public:
template <typename T>
void foo( T & t );
};

struct Intruder { int i; void (Leaking::*f)(); };

template <>
void Leaking::foo<Intruder>( Intruder & intruder ) {
intruder.i = i;
intruder.f = f;
}

int main() {
Leaking l;
Intruder i;
l.foo( i );
i.f(); // calls private member function!
}

Does that mean that all private members may as well be
public? Surely not.

Marc

Aug 25 '05 #4

P: n/a
That specialization trick is something. However, in order to take
advantage of it, the base class has to have a template member function.
It's perhaps unfortunate that the innards of a class could be accessed
this way. (Or rather, it's unfortunate that such access can't be
prevented since you can't stop a user from specializing a function.
The specialization would technically be considered a member of the base
class, even though the base can't prevent anybody from creating such a
member.) But it's an unfortunate consequence of using that particular
language feature.

(Incidentally, another such hole is pure virtual functions that do not
provide a stub implementation.)

My contention is that protected access itself doesn't make sense for
static members. I'm saying that this language feature whose purpose it
is to govern and regulate access to members is incapable of doing so
for static members. There doesn't have to be any opening available
to a class user allowing them to sneak in and become a member without
the knowledge of the base class. Trying to provide protected access
for a static member is not a well formed concept.

When I make a member private, it's well defined that the intention is
that only class members access the member. The language for the most
part checks this, even if there are a few language features that leave
a hole for producing new members after the class definition. Protected
nonstatic members also have a similar well-defined intention -- that
these members should only be manipulated by members of a derived class,
and then only those belonging to instances of that derived class. But
giving a static member protected access does not give a well defined
intention. What relationship should be in place between two entities
before one may access the other's protected static members? Ideally,
we'd like to say that one is a derived class of the other. But it's
much looser than that. Effectively, it is that a derived class of the
other exists that the first knows about or has control over. But that
doesn't make much sense from either a data-hiding point of view or an
object oriented design point of view, at least not to me.

The case that motivated this discussion is a project where a programmer
(not me, but I'm on the project too) gave a class Widget a protected
destructor. The idea is that only widgets should be able to create and
destroy other widgets (except a few friend classes that aren't
important here). However, the issue arose when a DerivedWidget1 tried
to delete a DerivedWidget2. This is illegal, since protected members
are only available to the class itself, not other classes that
inherited the same members. The workaround (besides making the
destructor public in the first place) is to make a protected static
function that does the delete for you. Then any derived class can
destroy any other derived class. However, this opens the floodgates
since there's no way to prevent anyone from creating a derived class.
Even private constructors/destructors/new operators/etc. won't have any
effect since instantiation is not required. At this point, the
destructor might as well be public in the first place.

Aug 25 '05 #5

P: n/a
Ram
Adam H. Peterson wrote:
I just made an observation and I wondered if it's generally known (or
if I'm missing something). My observation is that static protected
members are essentially useless, only a hint to the user. They don't
actually protect any encapsulation or anything, and for all the actual
protection they offer, they might as well be public.

For example:

class B {
protected:
static int i;
static void f();
};

int B::i=0;
void f() {
}

Nothing stops anybody anywhere from reading or changing B::i or from
calling B::f(). All anyone needs to do is create a derived class like
so:

struct D : B {
static int &i() { return B::i; }
static void f() { B::f(); }
};
[snip]

To me it seems you are incorrectly interpreting the access specifiers.
A protected specifier means that the members are accessible to the
derived classes, but it doesn't regulate in any way the derived classes
use them. They may as well expose them publicly, however that I'll call
a flaw in design except for may be some exceptional cases.
And, voila, the static protected method is (indirectly) publicly
accessible. Two lines of code overhead plus a line for each member to
be exposed. No one even has to create an instance, so private
constructors and destructors are no protection either.


Here, protected members are accessible through the interface which D
provides. Its still illegal to say,

B::i = something; // error
or
B::f(); // error

I don't see any discrepancy in this and this is independent to being
static/non-static. The only difference being that for non-static
members you need to instantiate an object to access them. As for
protection through constructor/destructors, I can as well access
protected constructor/destructor of a base through its public derived
interface.

Aug 25 '05 #6

P: n/a
Ben
Adam H. Peterson wrote:
I just made an observation and I wondered if it's generally known (or
if I'm missing something). My observation is that static protected
members are essentially useless, only a hint to the user. They don't
actually protect any encapsulation or anything, and for all the actual
protection they offer, they might as well be public.

For example:

class B {
protected:
static int i;
static void f();
};

int B::i=0;
void f() {
}

Nothing stops anybody anywhere from reading or changing B::i or from
calling B::f(). All anyone needs to do is create a derived class like
so:

struct D : B {
static int &i() { return B::i; }
static void f() { B::f(); }
};

And, voila, the static protected method is (indirectly) publicly
accessible. Two lines of code overhead plus a line for each member to
be exposed. No one even has to create an instance, so private
constructors and destructors are no protection either.

Is this generally known (and is it correct)? Maybe people seldom make
protected static members, so it's rarely an issue in practice.


OK, so what about:

class Stupid {
protected:
int i_;
public:
int& Expose() {return i_;}
};

No inheritance, static, or anything, and any old user can access the
*protected* member.

The problem is the design, not the language.

If you don't want subclasses to allow public access to a member of your
class, then don't allow the subclass access to it... make it a private
member and don't expose it in your class (by returning reference or
pointer).

Ben
--
I'm not just a number. To many, I'm known as a String...
Aug 25 '05 #7

P: n/a

"Adam H. Peterson" <al**********@gmail.com> wrote in message
news:11**********************@z14g2000cwz.googlegr oups.com...
[SNIP]
The case that motivated this discussion is a project where a programmer
(not me, but I'm on the project too) gave a class Widget a protected
destructor. The idea is that only widgets should be able to create and
destroy other widgets (except a few friend classes that aren't
important here). However, the issue arose when a DerivedWidget1 tried
to delete a DerivedWidget2. This is illegal, since protected members
are only available to the class itself, not other classes that
inherited the same members. The workaround (besides making the
destructor public in the first place) is to make a protected static
function that does the delete for you. Then any derived class can
destroy any other derived class. However, this opens the floodgates
since there's no way to prevent anyone from creating a derived class.
Even private constructors/destructors/new operators/etc. won't have any
effect since instantiation is not required. At this point, the
destructor might as well be public in the first place.


You mean that the DTOR was declared private because protected members are
inherited and accessible by derived classes. The way that you actually
unhinge the protection concept with classes does not only work with static
but also with ordinary member functions because you simply expose protected
functions. Naturally, the compiler and the language will let you do this
because it's your responsibility and you might (or might not) have a good
reason to do so. Sometimes it is even necessary to fix broken interfaces of
3rd party libs.

Anyway, the concept of public/private/protected is not to build a
high-security apparatus but rather to prevent fellow programmers from
unintentionally doing stupid things or indicating a certain behavior, like
having non copyable objects, to people using the classes.

Cheers
Chris
Aug 25 '05 #8

P: n/a
Ram wrote:
Here, protected members are accessible through the interface which D
provides. Its still illegal to say,

B::i = something; // error
or
B::f(); // error


True, but it might as well be legal. I don't see access protection as
something that's only provided in name and by using a bit of innocuous
syntax it can be stripped away. If I have:

class B {
protected:
void m_f();
static void s_f();
};

B b;

There's no way I can call b.m_f() without going through the class
interface. I can't get access to the b object by inheritance because
it's already instanced and the class author didn't screw up and break
encapsulation by making a naked accessor some other way. It's true
that if I create my own derived class, I can invoke the m_f() on
instances of that class, but that's a new class and I share
responsibility in it.

By contrast, I can create a three line code snippet that allows me to
call b.s_f() in all but name. So what kind of protection do I get by
declaring s_f() protected instead of public? What level of class
privilege do I have to have? If I'm a library vendor, what constraints
are imposed on calling s_f() that ensures any part of the integrity of
my library?

I'm not saying we should never declare protected static members. It
does serve as a useful hint to the class user. But it looks to me like
a "hint" is all that it provides.

Aug 25 '05 #9

P: n/a
Adam H. Peterson wrote:
Nothing stops anybody anywhere from reading or changing B::i or from
calling B::f(). All anyone needs to do is create a derived class like
so:
struct D : B {
static int &i() { return B::i; }
static void f() { B::f(); }
};

And, voila, the static protected method is (indirectly) publicly
accessible.


I don't see the point. Protected means that you can access it from derived
classes. You use it from a derived class, so you can acces it. You have
observed that the language works as it is designed to do.

--
Salu2
Aug 25 '05 #10

P: n/a
Adam H. Peterson wrote:
<snip>
The case that motivated this discussion is a project
where a programmer (not me, but I'm on the project too)
gave a class Widget a protected
destructor. The idea is that only widgets should be
able to create and destroy other widgets (except a few
friend classes that aren't
important here). However, the issue arose when a
DerivedWidget1 tried
to delete a DerivedWidget2. This is illegal, since
protected members are only available to the class
itself, not other classes that
inherited the same members.

<snip>

Does this work for you?

class WidgetBase {
public:
virtual ~WidgetBase() = 0;
};
WidgetBase::~WidgetBase() {}

class Widget : protected WidgetBase {
protected:
virtual ~Widget() = 0;
};
Widget::~Widget() {}

class DerivedWidget2 : public Widget {
public:
~DerivedWidget2() {}
};

class DerivedWidget1 : public Widget {
DerivedWidget2 * dw2;
public:
DerivedWidget1( DerivedWidget2 * w ) : dw2( w ) {}
~DerivedWidget1() {
/*##*/ delete static_cast<WidgetBase*>( dw2 ); dw2 = 0;
}
};

Marc

PS: Funnily (to me, I must confess), when not subclassing
Widget from another class, gcc 4.0 allows the delete dw2
w/o a cast, but errors out with 'Widget::~Widget is
protected in line ##'.
But I just got a compile error in for code of mine that
looks like
class Widget {
protected:
class Private;
};
class Widget::Private {
public:
class Strategy;
};
class Widget::Private::Strategy { /*...*/ };
namespace {
class FooStrategy : public Widget::Private::Strategy//1
{ /*...*/ };
class BarStrategy : public Widget::Private::Strategy//2
{ /*...*/ };
}

Gcc 4.0 compiles the code, VC 7.0 says //1 and //2 are
access violations.

Aug 25 '05 #11

P: n/a
Adam H. Peterson wrote:

(snip)
class B {
protected:
static int i;
static void f();
};

int B::i=0;
void f() {
}
(snip)
struct D : B {
static int &i() { return B::i; }
static void f() { B::f(); }
};


class B {
protected:
int i;
void f();
};

struct D : public B {
int &i() { return B::i; }
void f() { B::f(); }
};

For this discussion is the storage specifier "static" really required?
Or am I missing something?

Rgds,
anna

Aug 25 '05 #12

P: n/a
Adam H. Peterson wrote:

(snip)
Well, more to the point, considering how easy this is, what kind of
protection are you asking for when you make a protected static member?


I think that is the question that needs discussion here. By making
a member variable "protected" what is it that the class designer
intends to do?

My thoughts are along these lines.

1. Make a member variable protected, if you want to give full control
over it to derived classes. Full control means, read ability, write
ability, and exposing it more than what we like (returning a pointer
to it.)

2. If you only want to give read and write access, make the member
variable private, and provide appropriate getter and setter methods.

I would tend to look at class hierarchies as a set of co-operatively
designed classes. (Something like, if a group of threads, have to
share a resource in the correct manner, they have to co-operate.)

And remember that if somebody wants to manipulate the object using
"unconventional" methods, C++ cannot help. Thats my understanding.

Rgds,
anna

Aug 25 '05 #13

P: n/a

an****************@gmail.com wrote:
class B {
protected:
int i;
void f();
};

struct D : public B {
int &i() { return B::i; }
void f() { B::f(); }
};

For this discussion is the storage specifier "static" really required?
Or am I missing something?


In this case, you have exposed access only to those i's and f's that
are parts of B's that _also happen to be part of D's_. In this case, a
sloppily written derived class is only compromising base instances that
are subobjects of the poorly written derived class. In the case of a
static protected member, though, there is no constraint on how the
static member may be used. It's wide open to the world. If it takes a
B as an argument, for example (which I don't think is uncommon for
static members to do), anything you can do to a B in such a manner can
be done to _any_ B, not just B's that ere part of a bad derived D.

Aug 25 '05 #14

This discussion thread is closed

Replies have been disabled for this discussion.