Why can not I implicitly convert "Derived **" to "Base * const *"

  • Follow


I know to implicitly convert a "char **" to a "const char **" is not
permitted, but it is permitted to implicitly convert a "char **" to
"const char *const *". But why can not I implicitly convert a "Derived
**" to "Base *const *" by the followed code? I thought it is safe:

  class Base
  {
  public:
    virtual ~Base();
  };

  class Derived: public Base
  {
  };

  Derived ** p = NULL;
  Base * const * p2 = p;//It is not permitted!

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
0
Reply plainsong (1) 11/15/2003 10:24:26 AM

On 15 Nov 2003 05:24:26 -0500, plainsong@vip.sina.com (Plain Song) wrote:

 > I know to implicitly convert a "char **" to a "const char **" is not
 > permitted, but it is permitted to implicitly convert a "char **" to
 > "const char *const *". But why can not I implicitly convert a "Derived
 > **" to "Base *const *" by the followed code? I thought it is safe:

It has nothing to do with const or safety.  It is nonsense.

 >   class Base
 >   {
 >   public:
 >     virtual ~Base();
 >   };

 >   class Derived: public Base
 >   {
 >   };

 >   Derived ** p = NULL;
 >   Base * const * p2 = p;//It is not permitted!

     Base ** p3 = p;  // Not allowed.

P is a pointer to a Derived*.  A derived* is not a Base*.  P3 is
a pointer to a Base* and may not point to a Derived*.  The value
of a Derived* may convert to the value of a Base*, but the address
of a Derived* may not convert to the address of a Base*.

John

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
0
Reply John 11/16/2003 11:18:09 AM


On Sat, 15 Nov 2003 05:24:26 -0500, Plain Song wrote:

> I know to implicitly convert a "char **" to a "const char **" is not
> permitted, but it is permitted to implicitly convert a "char **" to
> "const char *const *". But why can not I implicitly convert a "Derived
> **" to "Base *const *" by the followed code? I thought it is safe:
> 
>   class Base
>   {
>   public:
>     virtual ~Base();
>   };
> 
>   class Derived: public Base
>   {
>   };
> 
>   Derived ** p = NULL;
>   Base * const * p2 = p;//It is not permitted!


That's because there is no relation between the base types of base** and
derived**, which are base*, and derived*, however since there is a
relatioship of parent-child between base and derived, which are the base
types for base* and derived*, a conversion between them is allowed. On the
other hand, char**, and const char* const* are both pointers to characters
differing only in their cv-qualifiers, so assigning to the const one the
non-const one is safe.

Regards,
-Dhruv.




      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
0
Reply Dhruv 11/17/2003 8:22:20 PM

Plain Song wrote:
> I know to implicitly convert a "char **" to a "const char **" is not
> permitted, but it is permitted to implicitly convert a "char **" to
> "const char *const *". But why can not I implicitly convert a "Derived
> **" to "Base *const *" by the followed code? I thought it is safe:
>
>   class Base
>   {
>   public:
>     virtual ~Base();
>   };
>
>   class Derived: public Base
>   {
>   };
>
>   Derived ** p = NULL;
>   Base * const * p2 = p;//It is not permitted!
>
Hi,

I'm replying to this posting because I asked the same question about a year
ago in comp.std.c++ and also answered it after I figured out the answer.
You can read my post at http://tinyurl.com/vh5k.

In short, the conversion is safe in terms of conformance (i.e. you will not
break the static type system in run time) but will be surprising for the
programmer since the result can actually be a temporary! This is because the
value representation of the pointer to the derived is not necessary the same
as the pointer to base (unlike cases where the difference is only in
cv-qualifier). Think about multiple inheritance.

The language is consistent since it forbids binding of temporary address to
pointer and this is general rule that also applies to your case.
OTOH The language allows binding of temporary to const reference and
therefore you *can* write:
Derived* dp = 0;
Base* const& rbp = dp; // temporary bounded to const reference

In your case you can manually do such conversions using extra variables
(manual temporaries) and standard conversions (i.e. no casts or user defined
conversions required):
Derived* dp = 0;
Base* temporary = dp;
Base** bpp = &temporary; // bind the "temporary" address

Rani



      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
0
Reply Rani 11/18/2003 7:48:33 PM

Rani, I read your original post. But I do feel that your original
quesiton 1 is legitimate.

Why the conversion from D* to B * const & is allowed?

Yes. It is "Convert D * to B * and then bind to const reference"

But just as you said:
"Although such conversion is perfectly safe it can be surprising to
the programmer and cause more harm then profit"

Declaring a reference to a variable winds up as a reference to a
temporary could be surprising to some programmers, I guess?

If D** to B*const* is disallowed, why not simply disallow D* to
B*const&?

Anyway, the same effect can be achieved by manually doing the
conversion as you pointed out:

B*const pb = pd;
B*const& ref = pb;

And that should be less confusing.

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
0
Reply ben_yu 11/20/2003 9:50:44 AM

Ben wrote:
 > Rani, I read your original post. But I do feel that your original
 > quesiton 1 is legitimate.
 >
 > Why the conversion from D* to B * const & is allowed?
 >
 > Yes. It is "Convert D * to B * and then bind to const reference"
 >
 > But just as you said:
 > "Although such conversion is perfectly safe it can be surprising to
 > the programmer and cause more harm then profit"
I meant for allowing binding of pointers to temporaries.

 > Declaring a reference to a variable winds up as a reference to a
 > temporary could be surprising to some programmers, I guess?
 >
 > If D** to B*const* is disallowed, why not simply disallow D* to
 > B*const&?

The rule that allows binding of r-value to const reference is important
especially since, as well known, it play role in making "const T&" an
important (read transparent) form of input argument. This rule also has
important implications on generic code. For example:

struct B {};
struct D : B {};

void f(vector<B*>& v, D* dp)
{
     find_if(v.begin(), v.end(), bind2nd(equal_to<B*>(), dp));
}

Rani



      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
0
Reply Rani 11/22/2003 10:52:42 AM

5 Replies
278 Views

(page loaded in 0.243 seconds)

Similiar Articles:











7/23/2012 5:24:40 PM


Reply: