Sign in to follow this  
Scythen

derived class access to base class protected members

Recommended Posts

Ok, we all know that you can access base class protected members within a member function like this
class A
{
protected:
	int m_int;
};
class B : public A
{
public:
	int Func()
	{
		return m_int;
	}
};

But what you cant do is this
//  A is from last example
class B : public A
{
public:
	int Func(const A &a)
	{
		return a.m_int;
	}
};

Unfortunately, this is exactly what I have a need for. In my case, A defines several virtual functions, some of which modify objects of type A. I'd like derived classes to be able to override them and change the implementation. I don’t want to be forced into making derived classes friends of the base class... that’s just ugly :( Anyone know of a nice way to get around this problem? [Edited by - Scythen on February 13, 2005 8:20:53 PM]

Share this post


Link to post
Share on other sites
No, thats not the problem... thanks for the try though.
It's a "cannot access protected member declared in class 'A'" error.

I'm not trying to modify m_int in the example.
This works fine

class B : public A
{
public:
int Func(const B &b)
{
return b.m_int;
}
};


Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Include an accessor method in A and use it to get the value you want

instead of

return a.m_int;

use

return a.getm_int();


Share this post


Link to post
Share on other sites
[headshake]Nope, unfortunately that’s no good either...
I don’t want to expose the protected data through public assessors.
I do want derived classes to have access to the base class protected data.
[crying] The more I think about this, the less I believe it is possible...

Share this post


Link to post
Share on other sites
Another possibility, though not particularly elegant, is to make the derived class a friend of the base class.

[edit] Example:
#include <iostream>

using namespace std;


class derived;

class base {
public:
base() : i( 2 ) {}
protected:
int i;

friend class derived;
};

class derived : public base {
public:
int again( const base &b ) {
return b.i;
}
};

int main() {
base b;
derived d;

cout << d.again( b );

cin.get();
return 0;
}


Regards,
jflanglois

[Edited by - jflanglois on February 13, 2005 10:49:26 PM]

Share this post


Link to post
Share on other sites
The following works, but is an ugly evil hack (it also seems to work on classes derived from A when A has a virtual function or a pure virtual function, but I only did a couple of quick tests...):
//  A is from last example
class C : public A
{
public:
int Func( const A& a)
{
return static_cast<const C&>(a).m_int;
}
};

edit: cleaned up stuff that meant nothing and took up space...[smile]

[Edited by - lucky_monkey on February 14, 2005 7:40:54 AM]

Share this post


Link to post
Share on other sites
Why do your derived classes need access to the implementation details of your base classes?

This isn't a good design and would have to be something very specific to justify doing it.

What exactly is the protected data?

A good way to look at it is to say 'my classes do something and provide a service, rather than contain something'.

Work out why you are deriving from your base classes, what service they provide. It may be that you can make them a member instead of deriving.

If you need to override virtual functions, see this article about making virtual functions private by default (from the Guru of the Week website)

Share this post


Link to post
Share on other sites
I don't even understand why this is not working in the first place! As far as I'm concerned the keyword protected implies that a class which is directly derived from the class in which the member is defined can do with the member whatever the hell it wants, regardless of whether it's 'bad design' or not. If the compiler doesn't support that then it's a crap compiler, period!

P.S. Hmmm, maybe I was a little too quick with my comment. I'm not sure what the standard has to say on trying to access protected members of an instance of the base class rather than on an instance of the derived class.

Share this post


Link to post
Share on other sites
Quote:
Original post by MaulingMonkey
Curse my inability to read late at night. Appologies D:
Yeah, it's getting pretty late here as well [smile]...it also doesn't help that no matter how it's done it's gonna be ugly, so the OP asking for a non-ugly solution is a little futile (someone's going to come along with an elegant solution now and prove me wrong [looksaround]...)

Quote:
Original post by Red Ant
I don't even understand why this is not working in the first place! As far as I'm concerned the keyword protected implies that a class which is directly derived from the class in which the member is defined can do with the member whatever the hell it wants, regardless of whether it's 'bad design' or not. If the compiler doesn't support that then it's a crap compiler, period!
It's because if you have three classes class A, class B : public A, and class C : public A you can upcast a C to and A. Should B's member functions then be able to operate on the internals of A? I don't think so, and obviously neither do some compiler writers [smile] It is a little weird though, 'cause you'd think from the descriptions of what the access specifiers do that you'd be able to do this, and it's not very well documented that you can't (at least, I couldn't find many references to it when I searched before)...

Share this post


Link to post
Share on other sites
Yeah, you're right, I just checked. Stroustrup demonstrates in 15.3.1



class Buffer {
protected:
char a[ 128 ];
// ...
};

class Linked_buffer : public Buffer { /* ... */ };

class Cyclic_buffer_ public Buffer {
// ...
void f( Linked_buffer* p ) {
// ...
a[ 0 ] = 0; // ok: access to cyclic_buffer's own protected member
p->a[ 0 ] = 0; // error: access to protected member of different type
}
};






P.S. On second thought, I would still think that it would be okay to do this in class Linked_buffer:


void g( Buffer& b ) {
b.a[ 0 ] = 0;
}



but I guess not.

Share this post


Link to post
Share on other sites
Well, just read up on it.
I agree with Stroustrup about the danger of protected members.

In my example I used a member variable but in reality I am only using member functions.

It looks like if I want to use my current design I'll have to make all derived classes friends of the base class[crying]
What really sucks is that all those classes will have access to private data as well[bawling]

petewood
Quote:
This isn't a good design and would have to be something very specific to justify doing it.


The design issue may have something to do with the whole problem.
This is not my exact design but I think it shows what I'm trying to do.

There is a base class with virtual Attach and Detach member functions, these manage a parent relationship. They are protected because only the base class and derived classes are allowed to change the parent relationship.
All of the member data is private.
There are also public virtual AddChild and RemoveChild functions which have base class references as their arguments.

So:
virtual void DerivedClass::AddChild(BaseClass &baseClass)
{
// Do derived class stuff and don’t call the base class impl because
// it does stuff that is not valid here
// use the protected member functions to modify the parent relationship
baseClass.Detach(); // remove any parent
baseClass.Attach(this);// add this as the new parent
}



I’m going to rethink my design; there is probably a better way to do this...

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this