POV-Ray : Newsgroups : povray.programming : C++ inheritance puzzler Server Time
28 Mar 2024 15:58:47 EDT (-0400)
  C++ inheritance puzzler (Message 4 to 13 of 13)  
<<< Previous 3 Messages Goto Initial 10 Messages
From: Thorsten Froehlich
Subject: Re: C++ inheritance puzzler
Date: 27 Nov 2010 09:40:47
Message: <4cf1186f@news.povray.org>
On 27.11.10 15:11, clipka wrote:
> Am 27.11.2010 15:03, schrieb Thorsten Froehlich:
>>> What the F*** am I doing wrong here?
>>
>> SP1 installed?
>
> Not sure; here's what the "about" window says:
 >
> Microsoft Visual Studio 2005 Standard Edition - ENU Service Pack 1 (KB926601)
> This service pack is for Microsoft Visual Studio 2005 Standard Edition - ENU.

Seems installed. Note that apparently there are several bugs related to 
C2248 that were not fixed in VC 2005.

	Thorsten


Post a reply to this message

From: Warp
Subject: Re: C++ inheritance puzzler
Date: 27 Nov 2010 09:45:23
Message: <4cf11983@news.povray.org>
clipka <ano### [at] anonymousorg> wrote:
> Hacking happily along at the POV-Ray code, I stumbled across this MS 
> Visual Studio 2005 C++ anomaly:

  AFAIK it's not an anomaly in VS, but a quirk in the C++ standard.

-- 
                                                          - Warp


Post a reply to this message

From: Le Forgeron
Subject: Re: C++ inheritance puzzler
Date: 27 Nov 2010 15:01:20
Message: <4cf16390@news.povray.org>
Le 27/11/2010 15:00, clipka nous fit lire :
> Hacking happily along at the POV-Ray code, I stumbled across this MS
> Visual Studio 2005 C++ anomaly:
> 
>   class A
>   {
>       protected:
>           void a() {}
>   };
> 
>   class B : public A
>   {
>       protected:
>           void b(A* other)
>           {
>               this->a();  // (1)
>               other->a(); // (2)
>           }
>   };
> 
> While (1) compiles fine, (2) raises an error C2248, "'A::a' : cannot
> access protected member declared in class 'A'"
> 
> What the F*** am I doing wrong here?

Issue of C++, or on the chair ?

(1) is ok because B is an A, so can access the protected function.
(2) is not allowed because a() of A is protected, so can only be called
by the object itself (in a gross simplification).

Works as designed.


Post a reply to this message

From: Warp
Subject: Re: C++ inheritance puzzler
Date: 27 Nov 2010 15:27:00
Message: <4cf16993@news.povray.org>
Le_Forgeron <jgr### [at] freefr> wrote:
> (2) is not allowed because a() of A is protected, so can only be called
> by the object itself (in a gross simplification).

  Actually that's not completely true. This is completely ok:

class A
{
 protected:
    void protectedFunctionOfA() {}
};

class B : public A
{
 public:
    void foo(B* other)
    {
        other->protectedFunctionOfA(); // ok
    }
};

  'protectedFunctionOfA()' is not being called by the object itself, yet
it's ok. However, the difference is that 'other' is of type B, in which
case it's allowed. However, if it was of type A, it would not be allowed:

    void foo(A* other)
    {
        other->protectedFunctionOfA(); // not ok
    }

  Basically, B is allowed to call the function only if the object is
(known to be) of type B, but not if it's only known to be of type A
(by static typing, ie. even if the object behind the pointer is in
reality of type B).

  Even if you did this, you would still get an error:

void B::foo()
{
    A* ptr = this;
    ptr->protectedFunctionOfA(); // not ok
}

  (The compiler *could* deduce in this case that 'ptr' is really pointing
to an object of type B, but there are only so many cases where it could
prove it for certain, and this could change from compiler to compiler.)

  Needless to say, gcc (and probably most other C++ compilers) will give
an error for that, so it just cannot be done. If you need to call the
protected section of the object, take a pointer of the derived type,
because that's what it has to be.

-- 
                                                          - Warp


Post a reply to this message

From: Le Forgeron
Subject: Re: C++ inheritance puzzler
Date: 28 Nov 2010 04:57:09
Message: <4cf22775$1@news.povray.org>
Le 27/11/2010 21:27, Warp nous fit lire :
> Le_Forgeron <jgr### [at] freefr> wrote:
>> (2) is not allowed because a() of A is protected, so can only be called
>> by the object itself (in a gross simplification).

I did write "in a gross simplification", didn't I ?

>   Needless to say, gcc (and probably most other C++ compilers) will give
> an error for that, so it just cannot be done. If you need to call the
> protected section of the object, take a pointer of the derived type,
> because that's what it has to be.
> 

Or "just" make B a friend of A. Or in fact, only the needed function of
B can be a friend of A.

Now, I would question the design any way for such function b
(as it is bypassing the objects' boundaries), but sometimes it's simpler
than redesign everything.

  class B;

  class A
  {
      protected:
          void a() {}
      friend void B::b(); // more restricted than "friend B;"
  };

  class B : public A
  {
      protected:
          void b(A* other)
          {
              this->a();  // (1)
              other->a(); // (2)
          }
  };


Post a reply to this message

From: clipka
Subject: Re: C++ inheritance puzzler
Date: 28 Nov 2010 12:29:17
Message: <4cf2916d$1@news.povray.org>
Am 27.11.2010 21:01, schrieb Le_Forgeron:
> (1) is ok because B is an A, so can access the protected function.
> (2) is not allowed because a() of A is protected, so can only be called
> by the object itself (in a gross simplification).
>
> Works as designed.

Is that so?

Why should (2) be prohibited when (1) is not? After all, the practical 
use of protected members is to hide implementation details from "alien" 
code; but the code in (2) is not alien - it must rely on that 
implementation detail called "a()" even if it just calls it on itself, 
so why prevent it from calling it on some other object of type A?

I can see how this /could/ be intended, but I'm not so sure whether it 
/is/ intended. At least it is unexpected for me, and makes life more 
cumbersome than necessary.


Post a reply to this message

From: Le Forgeron
Subject: Re: C++ inheritance puzzler
Date: 28 Nov 2010 13:27:39
Message: <4cf29f1b$1@news.povray.org>
Le 28/11/2010 18:28, clipka nous fit lire :
> Am 27.11.2010 21:01, schrieb Le_Forgeron:
>> (1) is ok because B is an A, so can access the protected function.
>> (2) is not allowed because a() of A is protected, so can only be called
>> by the object itself (in a gross simplification).
>>
>> Works as designed.
> 
> Is that so?
> 
> Why should (2) be prohibited when (1) is not? After all, the practical
> use of protected members is to hide implementation details from "alien"
> code; but the code in (2) is not alien - it must rely on that
> implementation detail called "a()" even if it just calls it on itself,
> so why prevent it from calling it on some other object of type A?
> 
> I can see how this /could/ be intended, but I'm not so sure whether it
> /is/ intended. At least it is unexpected for me, and makes life more
> cumbersome than necessary.

You should thinks "object oriented" as "public is what is available to
everyone, private is for myself only. Protected is a mixed path to allow
inheriting classes & friends to also have access to it.".

Whenever an instance X of an object has a reference to an instance Y
does not allow the methods of X to access the protected & private area
of Y, even if X & Y are from the same class.

Illustration with gun (protected method) & policeman (class):

Policeman X can use its gun (gun is protected, so other normal people do
not have access to it!)
Policeman X has to drive policeman Y (so X know about Y).
Nevertheless, Policeman X is not allowed to use the gun of Y directly.

X & Y are both Policemen, but each one keep his/her/its gun protected.

Or do you think the policeman from L.A. should be free to use the gun of
the policeman of N.Y. ? (free as: whenever, wherever, without even the
shadow of a control ?)


Post a reply to this message

From: Christian Froeschlin
Subject: Re: C++ inheritance puzzler
Date: 28 Nov 2010 18:22:29
Message: <4cf2e435$1@news.povray.org>
Le_Forgeron wrote:

> X & Y are both Policemen, but each one keep his/her/its gun protected.

But with this logic, the example Warp posted should also be forbidden.

I didn't try it myself but if the behavior is as described in this
thread it would mean protected access is restricted as follows:

Type/Instance This  Other

Parent        Ok    Fail

Same          Ok    Ok

Which I too find a bit odd.


Post a reply to this message

From: Le Forgeron
Subject: Re: C++ inheritance puzzler
Date: 29 Nov 2010 03:19:34
Message: <4cf36216@news.povray.org>
Le 29/11/2010 00:22, Christian Froeschlin a écrit :
> Le_Forgeron wrote:
> 
>> X & Y are both Policemen, but each one keep his/her/its gun protected.
> 
> But with this logic, the example Warp posted should also be forbidden.

Right, so you found a failure in the analogy when pushing it further
than intended.
I won't refine it, can you imagine policemen from the same specialised
activity sharing their gun ?

> 
> I didn't try it myself but if the behavior is as described in this
> thread it would mean protected access is restricted as follows:
> 
> Type/Instance This  Other
> 
> Parent        Ok    Fail
> 
> Same          Ok    Ok
> 
> Which I too find a bit odd.

Not so odd, if you consider that, from the point of view of knowing the
implementation, the failing case is just missing a friend to be ok;
Or turning it otherwise, the scope of calling other(B) when inside B is
ok, whereas the scope of calling other(A) when inside B is not.
(scope is different, hence the failure).

The sub-problem to forbid the warp's case would be if the called method
was a class method (not per instance, just per class)... it would
generate more problems.

Encapsulation principle: if you are the programmer in charge of B, you
do as you want with all the B, as long as it stays in B.

Protected:

    * Can be data and method members
    * Exactly same as private members for all practical purposes except
for the inheritance part
    * These members are inherited by a child of the class in which they
are declared
    * Their behaviour in the child class depends on how the inheritance
has been defined
    * If the inheritance is private these are private in the child
class; if it is public these are public in the child class and if the
inheritance in protected these are protected in the child class thus
allowing further inheritance.

Private:

    * Can be data or method members
    * Are accessible ONLY thru other methods of the same class where
they are declared
    * Cannot be accessed thru a class instance
    * Will not be inherited


-- 
Those who would give up Essential Liberty to purchase
a little Temporary Safety, deserve neither Liberty nor Safety.

Benjamin Franklin


Post a reply to this message

From: Warp
Subject: Re: C++ inheritance puzzler
Date: 29 Nov 2010 12:23:32
Message: <4cf3e194@news.povray.org>
clipka <ano### [at] anonymousorg> wrote:
> Why should (2) be prohibited when (1) is not? After all, the practical 
> use of protected members is to hide implementation details from "alien" 
> code; but the code in (2) is not alien - it must rely on that 
> implementation detail called "a()" even if it just calls it on itself, 
> so why prevent it from calling it on some other object of type A?

  I'd say you can think of it like when B inherits A, B inherits the
protected section of A, and it thus becomes also B's own protected section.
B can access its own protected section, but not A's protected section.
The distinction comes into play when you have an object of type B vs. an
object of type A. B can access the protected section of the former (because
it is part of B's protected section), but not the protected section of the
latter (because now it's purely A's protected section, not B's).

  (I'm not saying that this is a perfect design, or that it makes perfect
sense. I'm just describing the situation.)

  If you know that the object behind the pointer is really of type B, you
can make a cast to B. If the object has RTTI you can make a dynamic cast
to test if the object is of type B. If it's not of type B, then you just
can't call its protected section.

-- 
                                                          - Warp


Post a reply to this message

<<< Previous 3 Messages Goto Initial 10 Messages

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.