2015-05-03 9 views
6

A ma funkcję statyczną A :: create(), która tworzy wystąpienie A, wykonuje pewną inicjalizację i zwraca wskaźnik do niego. Chcę utworzyć podklasę A i mają podobną Create() func:co się stanie, jeśli rzut (wskaźnik do klasy A) na (wskaźnik do jego podklasy B) w C++

class B : public A { 
public: 
    static B* create(); 
    int val; 
    //... 
} 

w tym B :: create function() Mam wykonać następujące czynności:

B* B::create() { 
    auto b = (B*)A::create(); 
    b -> val = 0; 
    //... 
    return b; 
} 

Czy to właściwa droga to zrobić? Co stanie się po obsadzie?

Kontynuacja: A ma chroniony/prywatny konstruktor, Jak powinienem napisać B :: create() lub konstruktor B? Chcę się vars dziedziczone z mieć takie same wartości jak te tworzone przez A :: create() miałby

+6

Niezdefiniowane zachowanie. –

+0

Zależy od wielu rzeczy, czy to zadziała; ale nigdy nie polegaj na nieokreślonym zachowaniu. – CoffeeandCode

+0

Unikaj rzutowania w stylu C w C++ (zamiast tego użyj 'dynamic_cast'). Ponadto, jeśli klasy "A" i "B" dzielą podobne elementy danych, należy rozważyć użycie składni, kompozycji lub dziedziczenia, aby uniknąć powielania kodu. – Dai

Odpowiedz

5

obsady niczego sensownego nie zrobi chyba A::create() zwraca wskaźnik do B obiektu. Jeśli A::create() zwraca wskaźnik do obiektu, który nie jest B, masz niezdefiniowane zachowanie.

W C++ masz do czynienia z inicjalizacją obiektów za pomocą konstruktorów: inicjalizacja klas bazowych jest dziedziczona, a każda wyprowadzona może wykonać dowolną niestandardową inicjalizację, którą musi wykonać. Twój B::create() po prostu zwracają odpowiednio skonstruowanego obiektu:

B::B() 
    : A() // initialize base 
    , val(0) { 
     // other initialization 
} 
B* B::create() { return new B(); } 
+0

Wielkie dzięki! ale teraz B :: create() nie będzie przypisywał wartości do zmiennych dziedziczonych z A, ponieważ A :: created() robi. Moją kontynuacją byłby sposób użycia A :: create() w B :: create() lub B :: B(), aby zainicjować dziedziczone pola – snickers2029

+1

Powinieneś naprawić konstruktor 'A', więc inicjalizacja w' A :: create() 'nie jest potrzebny. Jeśli potrzebujesz użyć 'A :: create()' możesz użyć 'A * aptr = A :: create(); * this = * aptr; 'in' B''s constructor (i oczywiście odpowiednio zwolnij 'aptr'). Zdecydowanie odradzam robienie tego i zalecam naprawienie konstruktora 'A'. –

2

można zrobić klasa B Przyjaciel jak ten

class A { 
public: 
    static A* createA(); 
    int varA; 

private: 
    friend class B; // Make B a friend so that B can use private constructor of A 

    A() 
    { 
     cout << "In A constructor" << endl; 

     varA = 5; // Initialize members of A here 
    } 
}; 

A* A::createA() 
{ 
    return new A; 
} 

class B : public A { 
public: 
    static B* createB(); 
    int varB; 
private: 
    B() 
    { 
     cout << "In B constructor" << endl; 

     varB = -5; // Initialize members of B here 
    } 
}; 

B* B::createB() 
{ 
    return new B; 
} 

int main() 
{ 
    cout << "Create A" << endl; 
    A* x=A::createA(); 
    cout << "x->varA is " << x->varA << endl; 
    cout << endl; 

    cout << "Create B" << endl; 
    B* y=B::createB(); 
    cout << "y->varA is " << y->varA << endl; 
    cout << "y->varB is " << y->varB << endl; 
    cout << endl; 

    delete x; 
    delete y; 
} 

Kiedy nowy B jest wykonany, konstruktor get wywoływana automatycznie i członkowie A zostaną zainicjowani.

wyjściowa wynosi:

Create A 
In A constructor 
x->varA is 5 

Create B 
In A constructor 
In B constructor 
y->varA is 5 
y->varB is -5 

Innym sposobem jest, aby konstruktor chronionego zamiast prywatne.