|
Maximilien wrote: all members in structs should be public
no. this is true only is you don't redefine the visibility (which is actually done here with protected: )
TOXCCT >>> GEII power
[VisualCalc 3.0 updated ][Flags Beginner's Guide new! ]
|
|
|
|
|
>>>It's a difference in the way structs differ from classes
No it's not. Changing these to "classes" with public: at the beginning has no effect (I've tried it)
|
|
|
|
|
Dave Schumann wrote: No it's not.
Sure it is.
Dave Schumann wrote: Changing these to "classes" with public: at the beginning has no effect (I've tried it)
It won't have an effect until you put A::value into a public section. This is the default with a struct . So, you'll either need:
struct A
{
A* partner;
void doodah()
{ ++partner->value; }
int value;
}; or
class A
{
public:
A* partner;
void doodah()
{ ++partner->value; }
int value;
};
"The largest fire starts but with the smallest spark." - David Crow
"Judge not by the eye but by the heart." - Native American Proverb
|
|
|
|
|
>>>Sure it is.
No - it's not. You said it has something to do with struct vs. class - it doesn't. Change them to clases with public scope at the beginning and everything will be the same. What you did was remove the "protected:" which has nothing to do with it being a struct or not.
I declared "protected:" for a reason, not because I like having things not compile. This is a toy version of a much larger problem. I can't stand posters who post 20 pages of code so I figured I'd boil the issue down. In fact in my case the issue is accessing a *function*...and there's virtual stuff and blah blah blah. Now you're getting bored, appropriately. None of that is relevant to the compiler error which I can't understand.
|
|
|
|
|
Dave Schumann wrote: I declared "protected:" for a reason, not because I like having things not compile. This is a toy version of a much larger problem. I can't stand posters who post 20 pages of code so I figured I'd boil the issue down. In fact in my case the issue is accessing a *function*...and there's virtual stuff and blah blah blah. Now you're getting bored, appropriately. None of that is relevant to the compiler error which I can't understand.
Since you aren't giving the details of your larger problem (understandably), I will only mention that almost always, protected should be replaced by private. See Effective C++ by Scott Meyers for details.
If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week
Zac
|
|
|
|
|
Zac Howland wrote: I will only mention that almost always, protected should be replaced by private.
maybe, but here, the protected member is accessed by a children... so, putting it private will cause a new problem in his code.
TOXCCT >>> GEII power
[VisualCalc 3.0 updated ][Flags Beginner's Guide new! ]
|
|
|
|
|
toxcct wrote: maybe, but here, the protected member is accessed by a children... so, putting it private will cause a new problem in his code.
That hits to the design issue I was referring to.
If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week
Zac
|
|
|
|
|
So would it be permissible to just add a "getter" method to A ?
"The largest fire starts but with the smallest spark." - David Crow
"Judge not by the eye but by the heart." - Native American Proverb
|
|
|
|
|
Yes, me too. It's not complaining about accessing "partner" - it's complaining about accessing "partner::value" even though B is a child of A and "value" is a protected member.
This is a toy version of a real problem I'm having (I trusted that the "A", "B", "foobar", and "doodah" names would make that relatively obvious ). My real problem involves much larger *classes* (not structs...again this is a toy problem) and the real-life version of "A" is not easy to modify. I was honestly shocked I was able to write this toy version that doesn't compile (it really doesn't - just cut'n'paste and see for yourself). I assumed that the problem was some complicated thing about my larger classes and their relationships or whatever...but no, it's really not letting me do this.
|
|
|
|
|
Dave Schumann wrote: It's not complaining about accessing "partner"
And it won't. partner has public access. If it complained about that, I would be really shocked.
This link may help you as well: C++ Protection
If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week
Zac
|
|
|
|
|
Yeah - I found the relevant portion of the standard. It actually specifies an EXTRA CHECK for cases like this. Why?? See "solution" below for section and quote.
|
|
|
|
|
I believe the reason why is that you could completely circumvent protection by using inheritence if they did not do this check.
If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week
Zac
|
|
|
|
|
well you can basically "completely circumvent" protection anyway. For example:
LIBRARY:
class A
{
protected:
int value;
};
MY CODE:
//now let's say I want to access value in an 'A' object I have. I just write this:
class A_breaker: public A
{
public:
int* accessValue()
{ return &value; }
};
void my_function (A& my_a)
{
int* value_ptr = ((A_breaker&)my_a).accessValue();
//now I can do anything
}
...so if they were trying to make "protected" bulletproof, they didn't succeed at all. (I've actually compiled the above and it's perfectly legal...and, incidentally, the cast to A_breaker is perfectly safe since A_breaker adds no data)
-- modified at 13:01 Wednesday 12th July, 2006
|
|
|
|
|
I doubt they were trying to make it bulletproof. Chances are they were trying to provide as strict a mechanism for it as possible while still allowing for old C-Style code to compile.
If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week
Zac
|
|
|
|
|
Easy and more correct fix:
class A
{
public:
A* partner;
void doodah() { ++partner->value; }
int getValue() const { return value; }
void setValue(int newValue) { value = newValue; }
protected:
int value;
};
class B: public A
{
public:
void foobar() { partner->setValue(partner->getValue() + 2); }
};
If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week
Zac
|
|
|
|
|
You've provided public accessors to "value". If I wanted value to be accessible publicly, I'd just make it public.
I'm not putting "protected" in just to make life hard. I actually don't want any outside classes modifying "value". If you make "setValue" protected above - which is the whole point - then you've violated the restrictions I want on "value".
|
|
|
|
|
Dave Schumann wrote: You've provided public accessors to "value". If I wanted value to be accessible publicly, I'd just make it public.
Which would be even worse.
Dave Schumann wrote: I'm not putting "protected" in just to make life hard. I actually don't want any outside classes modifying "value". If you make "setValue" protected above - which is the whole point - then you've violated the restrictions I want on "value".
While I'll let you read Meyer's argument for not using protected for yourself, I will point out another glaring point:
Why do you have a pointer to A as a member of class A? From experience, every single time I've seen that type of code, it has been due to poor design. What is it that your larger problem is trying to accomplish?
If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week
Zac
|
|
|
|
|
Zac Howland wrote: Why do you have a pointer to A as a member of class A? From experience, every single time I've seen that type of code, it has been due to poor design
Really? Do you really mean that? I'll let you re-read it for a second...
...
would this just be too obvious?
class Node
{
Node* next;
void* data;
};
i.e., the basic definition of a linked list?
|
|
|
|
|
Sorry, there was suppose to be an "almost" before the "every single".
Reinventing something that already exists (linked lists) is rarely ever necessary.
If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week
Zac
|
|
|
|
|
Actually I thought of a better example. Is there any LEGITIMATE reason (other than the language lawyers at ISO) that I shouldn't be able to do this?...
class Node
{
public:
virtual void doSomething() {}
protected:
Node* child;
Node* parent;
};
class Int_Node : public Node
{
int data;
public:
virtual void doSomething()
{
//first, check list validity
if (parent->child != (Node*)this)
cout << "Oh No!";
....
}
};
now we've discovered today that this won't work since when you're an Int_Node you can't access parent->child. But you SHOULD be able to since you're a Node!!
|
|
|
|
|
You could just do it this way:
class MyJunk
{
public:
void DoSomething() {}
private:
int _Data;
};
std::list<MyJunk> myJunkList;
If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week
Zac
|
|
|
|
|
This is apparently how it's supposed to work. Section 11.5.1 of the ISO C++ standard:
Except when forming a pointer to member (expr.unary.op), the access must be through a pointer to, reference to, or object of the derived class itself (or any class derived from that class)
They provide a very similar example to mine except it looks more like this:
void foobar(A& a)
{ a->value += 2;}
I think this is dumb beyond belief. Why can't B do what A can do? B is an A. C++ often goes 90% of the way to supporting class inheritance and then stops. This is just another frustrating example.
|
|
|
|
|
Dave Schumann wrote:
Except when forming a pointer to member (expr.unary.op), the access must be through a pointer to, reference to, or object of the derived class itself (or any class derived from that class)
Here's a way to get around that rule (11.5.1), adapted from a guy named Olivier Langois:
struct A
{
A* partner;
void doodah()
{ ++partner->value; }
protected:
static int& access_value(A& a)
{return a.value;}
int value;
};
struct B: public A
{
void foobar()
{ access_value(*partner) += 2; }
};
I've added a PROTECTED static access_value() function in A. B can call it since it's a child. The ISO police go down in flames again. Huzzah!!!
|
|
|
|
|
Isn't this normal behaviour.
I mean i learned the rule like this.
"You can't access any protected or private members/functions of a object of another class/structure"
since the object partner isn't the same type as B any object of B can't access the protected members of the A object.
B can however access the protected members of itself which he inheritted from A. These are no longer A member but are now B members.
Thats why you can access partner (inherrited) but not the protected member value of the object partner. You can alsoo access your own inherrited member value.
that just my 2 cents
codito ergo sum
|
|
|
|
|
Dave Schumann wrote: I think this is dumb beyond belief.
I disagree. I also agree with some previous postings regarding the poor design. Improved design according to encapsulation principles might look something like this. ( not accounting for "partner" creation issues )
struct A
{
void doodah()
{ ++partner->value; }
protected:
int& partnerValue(){ return partner->value;}
private:
A* partner;
int value;
};
struct B : public A
{
void foobar()
{ partnerValue() += 2; }
};
"Just about every question you've asked over the last 3-4 days has been "urgent". Perhaps a little planning would be helpful?" Colin Angus Mackay in the C# forum
led mike
|
|
|
|