|
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
|
|
|
|
|
After reading these many posts (although many of them seemed to miss the point entirely) I agree with what as already been stated: the "protected" keyword in A allows access from B to protected members in B inherited from A. Not members from A.
So, there is no real way to make this access legal. B can access all the protected members of B, but not the protected members of A. I do think that this is a design error, although I believe that someone has thought about it and found enough arguments to justify this protection. I would be happy to leave it to the lawyers to argue about it.
Meanwhile, to get around the issue, you could force a static cast on the partner. For example:
struct A
{
A* partner;
void doodah()
{ ++partner->value; } //this is legal
protected:
int value;
};
struct B: public A
{
void foobar()
{ ((B*)partner)->value += 2; } //but this isn’t
};
This code compiles. You may use this code safely because you know that B contains an A. So, the static cast can be used safely if you ensure that you do not use any of B's features on the cast A's partner pointer.
Anyway, with the static cast solution, you can keep the value protected, and still use it from inside B. The code in foobar() is the only one accessing the "value" (this gives you a "per line" control, as oposed to class or function access provided by the use of "friend").
I hope this helps (although I'm sure you will see it as a workaround, I know I do),
Rilhas
|
|
|
|
|
Note that for "plain value" the compiler knows that the value is a member of a B; for "partner->value" it only knows that value is a member of an A.
There is a rule that says that "protected" gives access only to a base of an object of "your own class." That rule was introduced after some pretty horrific bugs appeared where the equivalent to "partner" in your code pointed to a completely different class C that just happened to have the same base (A). There is a discussion of this in D&E.
"Money talks. When my money starts to talk, I get a bill to shut it up." - Frank
"Judge not by the eye but by the heart." - Native American Proverb
|
|
|
|
|
Hi,
I am currently writing a namespace extension. I have an IShellFolder implementation, that implements such functions as 'SetNameOf' (called when the user renames an item). However, after calling SHChangeNotifiy (with PIDLs fully qualified, i.e relative to the desktop) my IShellView DOESN'T refresh the changes.
I haven't implemented my own IShellView, I use one created by SHCreateShellFolderView. I would imagine this IShellView would automatically respond to SHChangeNotify, but it doesn't. If I force a refresh by hitting F5 the correct renamed file is then displayed.
Does anyone have any ideas as to why SHChangeNotify isn't working? Any help would be appreciated.
Many thanks,
Dave
Dave Kerr
codechamber@hotmail.com
http://www.codechamber.com
|
|
|
|
|
Is there any way to label the stops on a slider control?
E.g.
| | |
-1 0 1
|
|
|
|
|
Yes, you have to draw it your own.
|
|
|
|
|
Would this be done using owner draw?
|
|
|
|
|