views:

79

answers:

7

Edit - Put the question into context a bit more.

Given:

struct Base
{
    ...
};
struct Derived : public Base
{
    ...
};
class Alice
{
    Alice(Base *const _a);
    ...
};
class Bob : public Alice
{
    Bob(Derived *const _a);
    ...
};

When I try to implement

Bob::Bob(Derived *const _d) : Alice(static_cast<Base*const>(_d)) { }

it does not work. a const_cast doesn't make sense to me as I don't want to change the constness, and I'm not changing what I'm pointing to, so why then does g++ tell me

invalid static_cast from type ‘Derived* const’ to type ‘Base* const’

? If I leave out the cast, it says

no matching function for call to ‘Alice::Alice(Derived* const)’

If anyone could shed any light on this It'd be much appreciated.

+1  A: 

You don't need any cast at all. You have const pointers, not pointers to const objects. And it's legal to assign the address of a derived object to a pointer-to-base without a cast.

Oli Charlesworth
parallel
@parallel: You've implicitly declared your constructors private, so `Bob` cannot see `Alice::Alice(Base *)`. As an aside, noe that you don't need `const` in this context (i.e. function prototypes).
Oli Charlesworth
@Oli Charlesworth: The compiler should be able to *see* it. Access control does not affect visibility. Yet, the compiler should not be able to *access* it. In cases like that the error message usually looks differently. I suspect that the code is fake.
AndreyT
@AndreyT: I was using the term "see" colloquially!
Oli Charlesworth
+1  A: 

I have a theory. What if during derivation you had accidentally forgotten to specify that the derivation is public? In this case it would be private by default and the above conversion would be inaccessible.

Are you sure you wrote

class Derived : ***public*** Base {...}

?
Or maybe you forgot public? Just a theory...

Armen Tsirunyan
I think most likely `Derived` and `Base` are simply unrelated types.
Alf P. Steinbach
It is derived public.
parallel
Derived is declared as: `struct Derived : public Base {...};`
parallel
@Parallel: What compiler are you using?
Armen Tsirunyan
And also, names starting in an underscore... I dunno... what if this caused the problem, these are technically banned, aren't they? Or are they reserved only if followed by uppercase? Only wild theories can apply here... :)
Armen Tsirunyan
@Armen - there're some conventions to put underscore in the beginning of a variables/methods, that are private. This helps then to be listed at the beginning or at the end of the list with possible choices (when type operator. or operator-> after an object). As I know, it's quite dangerous to have names, starting with double underscore, as most compilers use names, starting with __ (kinda reserved names)
Kiril Kirov
I changed the question to give it more context. I probably shouldn't have tried to simplify it, after all it's me who's asking for help :(
parallel
@parallel: you have unrelated types `Alice` and `Base`.
Alf P. Steinbach
@Alf: And why should they be related?
Armen Tsirunyan
@Armen: because the code passes a `Base*` to the `Alice` constructor, which expects an `Alice*`.
Alf P. Steinbach
@Alf: As far as I can see Alice's constructor expects Base*...
Armen Tsirunyan
@Armen: dunno, there was an `Alice*` last I looked, at least as reported by my eyes. Currently the code has no problems. And as such there is no question to answer...
Alf P. Steinbach
+1  A: 

You have unrelated types Alice and Base. Change the Alice constructor to take a Base*.

By the way, I suspect that you have your const placements wrong.

Cheers & hth.,

Alf P. Steinbach
@Alf: Yeah, most probably he does, but still this is a mystery...
Armen Tsirunyan
I intended the pointers to be const, not the objects pointed to.
parallel
@parallel: It usually doesn't make sense to declare functions that take const parameters, since they are equivalent as declarations to those who take without const. The only difference is in the definition where you can't change the parameter
Armen Tsirunyan
A: 

The problem was that Derived was an incomplete type, i.e. forward declared. I'm afraid I've been giving everyone a hard time :( The answer popped up when Kiril Kirow proposed using a dynamic-cast, upon which g++ spat out this slightly more helpful error:

error: cannot dynamic_cast ‘_d’ (of type ‘struct Derived* const’) to type ‘struct Base* const’ (source is a pointer to incomplete type)

Unfortunately, I had forward declared Derived, but I hadn't realized it was relevant, and it was hidden several headers further down, which would have had me posting too much code here. Sorry everyone, but I hope this at least helps somebody else later.

parallel
+1  A: 

This compiles perfectly on g++ 4.4.3, no even warnings:

#include <iostream>

struct Base
{
    Base()
    {
    }
};

struct Derived : public Base
{
    Derived() {}
};

class Alice
{
public:
    Alice( Base *const _a )
    {
        std::cout << "Alice::Alice" << std::endl;
    }
};

class Bob : public Alice
{
public:
    Bob(Derived *const _a) 
        : Alice( static_cast< Base * const >( _a ) )
    {
        std::cout << "Bob::Bob" << std::endl;
    }
};

int main()
{
    Derived* pDer = new Derived();
    Bob b( pDer );
    return 0;
}
Kiril Kirov
Also, I'd recommend you to use dynamic_cast in such cases, surround the cast in try-catch block and check if the returned value is not NULL. By the way, you don't really need any cast here.
Kiril Kirov
@Kiril Kirov: `dynamic_cast` makes absolutely no sense here at all. Firstly, there's no need for any cast at all. Secondly, the purpose of `dynamic_cast` is to be used for downcasts and cross-casts. This is an *upcast*. There's no meaningful reason to use `dynamic_cast` for upcasts.
AndreyT
Okay, noted for static_cast and dynamic_cast. I didn't really know that, thanks (:
Kiril Kirov
A: 

The only problem here is that Alice::Alice is private in Alice. Bob has no access to Alice::Alice.

There are no problems with the cast whatsoever. In fact, you don't need a static_cast for it. It should be converted implicitly.

The static_cast you currently have is valid, except for a redundant const qualifier in the target type. That const there simply makes no sense, but it is not an error.

Why your compiler is issuing these bizarre error messages is not clear to me. I suspect that the code you posted is fake.

AndreyT
A: 

While I am not sure (too little context) I think you might have meant Base const * and Derived const *.

Base const * is a pointer to constant Base object. Base * const is a constant pointer to modifiable Base object.

Tomek
I intended the pointers to be const, not the objects pointed to.
parallel