Hi.
Visual C++ reports error 2440 for the following code:

struct a_t { int i;};
struct b_t:a_t { int j;};
b_t* pb = 0;
a_t* const * ref_pa = &pb; // Error 2440 reported for no reason at all. 

I cannot see why this should give an error, the base class pointer reference is declared as referring to constant pointer memory. Thus, the contents cannot be changed.

It is a greatly deplorable since it hinders a function call of this kind:

    void f( a_t* const * pointer_list) {}
    b_t* list[10];
    // Call of f with the b_t pointer list:
    f(list); // Gives compiler error 2440...

This forces unnatural rewriting of the code. In the above case one might have a host of
other subclasses of a_t and one needs to write a function declaration for each single type.

The error message tells you what you have to do

error C2440: 'initializing' : cannot convert from 'b_t **' to 'a_t *const *'
1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast a_t* const * ref_pa = reinterpret_cast<a_t**>(&pb);

I cannot see why this should give an error, the base class pointer reference is declared as referring to constant pointer memory.

The problem isn't about const, it's about an added level of indirection. a_t** and b_t** are incompatible types; you were expecting polymorphism to be recursive through all levels of indirection, which isn't the case.

To get a reference or pointer to a pointer to a derived class, you'd need to go through an intermediate pointer to the base class:

struct base {
    virtual void foo() { cout << "base\n"; }
};

struct derived: public base {
    virtual void foo() { cout << "derived\n"; }
};

derived* pd = new derived;
base* temp = pd;
base** ref_pb = &temp;

(*ref_pb)->foo();

Thanks for the posts. Both tells us what to do, and my current solution is typecasting in the function call.

However, could anyone give an example of how there could be any misuse of having a base class * const * variable storing the address of a pointer to a derived class?
It would be of great interest.

A pointer to a derived class and a pointer to a base class, for the same object, are not guaranteed to hold the same address in memory. Often, they do, but sometimes they don't. For example, when using virtual inheritance and/or multiple inheritance, then, for the same object, the pointers to different classes in the hierarchy are not the same. In that sense, an implicit cast from a derived class to a base class does not just "reinterpret" the address value as being an address to the base class, it also applies an offset to that address value. So, because the actual address value can be required to change between Derived* and Base*, to do the conversion, it creates a new pointer of type Base*, and since it is a temporary (if you don't assign it to a variable), its address cannot be taken. That is why a conversion from Derived** to Base** is impossible, you need, as Narue posted, an intermediate variable of type Base* whose address can be taken (lvalue).

Thanks! So the compiler does not do a typechecking seeing that the address offset is zero.

>>So the compiler does not do a typechecking seeing that the address offset is zero.
No, the C++ compiler follows strict rules, the standard is clear and will not be broken for this kind of trivial issues. Basically, since there are cases where this kind of cast would not be valid, it is simply forbidden.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.