2010-10-16 27 views
5

Edytuj - Umieść pytanie w kontekście nieco więcej.rzut Pochodny * const do Bazy * const

Dane:

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

Kiedy próbuję wdrożyć

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

to nie działa. const_cast nie ma sensu do mnie jak nie chcę, aby zmienić constness, a ja nie zmienia, co mam wskazując, więc dlaczego wtedy nie g ++ mi

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

? Jeśli pominię rzutowanie, będzie to oznaczać, że ktoś może rzucić na to jakiekolwiek światło. Byłoby to bardzo doceniane.

+0

Jeśli 'Derived' ma faktycznie' Bazę' jako klasę podstawową, to (a) ten kod nie powinien powodować żadnych błędów (może to spowodować ostrzeżenie, że kwalifikator const dla 'static_cast' target nic nie robi) i (b) możesz po prostu przypisać '_derived_ptr' do' _base_ptr' zgodnie z sugestią Oli. –

+0

Myślę, że masz const po niewłaściwej stronie: 'Base * const x;' Tutaj x jest wskaźnikiem const dla 'standardowej bazy' (tzn. Nie można zmienić x). 'Base const * x' Tutaj x jest wskaźnikiem do' const Base' (tzn. Obiekt wskazywany przez x jest const). –

+0

Rzeczywiście mam wskaźniki jako const, a nie obiekty wskazane. Ponadto, to pytanie nie jest całkowicie poprawne (tylko po to, aby powstrzymać mnie przed zalaniem pytania kodem), ponieważ używam statycznego rzutowania w konstruktorze wywołującym jego konstruktor macierzysty: 'SomeClass :: SomeClass (Derived * const _d): SomeBase (static_cast (_d)) {} ' – parallel

Odpowiedz

5

Problem polegał na tym, że pochodne był niekompletny rodzaju, to znaczy do przodu uznany. Obawiam się, że już daje każdemu ciężko :( Odpowiedź pojawiła się, gdy Kiril Kirow proponuje stosując dynamiczną odlewu, na której g ++ wypluł to nieco bardziej pomocne błąd:

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

Niestety, Napisałem już o Derived, ale nie zdawałem sobie sprawy, że to jest istotne, i zostało ukryte kilka nagłówków w dół, co spowodowałoby, że wysłałem tu zbyt dużo kodu, przepraszam wszystkich, ale mam nadzieję, że to przynajmniej pomoże później komuś innemu.

1

Nie potrzebujesz żadnej obsady. Masz wskaźniki const, a nie wskaźniki do obiektów const. I legalne jest przypisywanie adresu obiektu pochodnego do wskaźnika do bazy bez rzutowania.

+0

Żadna obsada nie mówi mi "brak pasującej funkcji dla połączenia z" Alice (Derived * const &) "' – parallel

+1

@parallel: Niejawnie zadeklarowałeś swoje konstruktory jako prywatne, więc 'Bob' nie może zobaczyć' Alice :: Alice (Base *) '. Na marginesie, noe, że nie potrzebujesz "const" w tym kontekście (tj. Prototypy funkcji). –

+0

Kompilator powinien móc * zobaczyć * to. Kontrola dostępu nie wpływa na widoczność. Jednak kompilator nie powinien mieć * dostępu * do niego. W takich przypadkach komunikat o błędzie zazwyczaj wygląda inaczej. Podejrzewam, że kod jest fałszywy. – AnT

1

Mam teorię. Co się stanie, jeśli podczas derywacji przypadkowo zapomnisz określić, że wyprowadzenie jest publiczne? W tym przypadku domyślnie byłby on prywatny, a powyższa konwersja byłaby niedostępna.

Na pewno napisał

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

?
A może zapomniałeś publicznych? Tylko teoria ...

+0

Myślę, że najprawdopodobniej "Derived" i "Base" są po prostu niezwiązanymi typami. –

+0

Jest pochodną publiczną. – parallel

+0

Pochodne są deklarowane jako: 'struct Derived: public Base {...};' – parallel

0

Masz niepowiązanych typów Alice i Base. Zmień konstruktor Alice, aby uzyskać Base*.

Przy okazji, I podejrzewam, że ma niewłaściwe miejsca docelowe const.

zdrowie & HTH.,

+0

Tak, najprawdopodobniej tak, ale wciąż to jest tajemnica ... –

+0

Chciałem, aby wskaźniki były stałe, a nie wskazywane obiekty. – parallel

+0

@parallel: Zazwyczaj nie ma sensu deklarowanie funkcji, które pobierają parametry const, ponieważ są one równoważne jako declaat jony dla tych, którzy biorą bez stałej. Jedyną różnicą jest definicja, w której nie można zmienić parametru –

1

To kompiluje doskonale na g ++ 4.4.3, nie ma nawet ostrzeżenia:

#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; 
} 
+0

. Zalecam również, aby w takich przypadkach używać dynamic_cast, otaczać rzut w bloku try-catch i sprawdzać, czy zwrócona wartość nie ma wartości NULL. Nawiasem mówiąc, naprawdę nie potrzebujesz tutaj żadnej obsady. –

+1

'dynamic_cast' w ogóle nie ma sensu. Po pierwsze, w ogóle nie ma potrzeby wykonywania rzutów. Po drugie, cel 'dynamic_cast' ma być używany dla downcastów i rzutów krzyżowych. To jest * upcast *. Nie ma żadnego sensownego powodu do używania 'dynamic_cast' dla upcastów. – AnT

+0

Dobra, odnotowano dla static_cast i dynamic_cast. Tak naprawdę nie wiedziałem, dziękuję (: –

0

Jedynym problemem jest to, że Alice::Alice jest prywatne w Alice. Bob nie ma dostępu do Alice::Alice.

Nie ma żadnych problemów z obsadą. W rzeczywistości nie potrzebujesz do tego static_cast.Powinien być niejawnie konwertowany.

Aktualnie posiadana wersja static_cast jest ważna, z wyjątkiem nadmiarowego kwalifikatora const w typie docelowym. Ten const po prostu nie ma sensu, ale nie jest błędem.

Nie jest dla mnie jasne, dlaczego Twój kompilator wydaje te dziwaczne komunikaty o błędach. Podejrzewam, że opublikowany przez Ciebie kod jest fałszywy.

0

Chociaż nie jestem pewien (zbyt mało kontekstu) Myślę, że masz na myśli Baza const * i pochodnego const *.

Baza const * to wskaźnik do stałego obiektu Base. Baza * const to stały wskaźnik do modyfikowalnego obiektu Base.

+0

chciałem, aby wskaźniki były stałe, a nie wskazywane obiekty. – parallel