2016-04-10 57 views
5

Mam klasę, która jest pochodną od innej, używam tablicy wskaźników klasy bazowej do przechowywania instancji klasy pochodnej, ale ponieważ tablica jest z klasy bazowej, I nie można uzyskać dostępu do elementów należących do klasy pochodnej za pomocą notacji wskaźnika, czy mogę uzyskać dostęp do tych elementów za pomocą prostego polecenia lub czy powinienem przepisać klasę podstawową, aby zdefiniować element i użyć go tylko w klasie pochodnej?Członek dostępu klasy pochodnej od wskaźnika klasy bazowej

Przykład:

class A { 
public: 
    int foo; 
}; 

class B : public A { 
public: 
    char bar; 
}; 

class C : public A { 
    int tea; 
}; 

int main() { 
    A * arr[5]; 
    arr[0] = new B; 

    char test = arr[0]->bar; //visual studio highlights this with an error "class A has no member bar" 

    return 0; 
} 
+1

O ile wiem, nie można uzyskać dostępu do elementu klasy pochodnej od wskaźnika klasy bazowej. Po prostu dlatego, że klasa bazowa w ogóle go nie rozpoznaje. Możesz jednak uzyskać dostęp do elementu klasy bazowej ze wskaźnika klasy pochodnej, ponieważ hierarchia mówi, że ** członkowie publiczni klasy bazowej są teraz także członkami klasy pochodnej **. –

+0

Ale dane technicznie istnieją, prawda? Czy mogę to zrobić za pomocą przesunięcia pamięci? – Stephen

+2

Do tego służą wirtualne metody. Jeśli jeszcze nie nauczyłeś się metod wirtualnych w swojej klasie C++, teraz jest to doskonała okazja, aby to zrobić. –

Odpowiedz

6

Nie mogę uzyskać dostępu członków należących do klasy pochodnej z notacji wskaźnik

Jest to zgodne z projektem: Nie poinformować kompilator, że obiekt wskazywany przez wskaźnik jest typu pochodnego.

jest to możliwe dla mnie, aby uzyskać dostęp do tych elementów za pomocą prostego polecenia

Można to zrobić, jeśli wykonać static_cast<B*>(arr[0]) jeśli jesteś w 100% pewien, że strzałka wskazywała B, ale rozwiązanie odlewania powinien być w ostateczności. Zamiast tego, należy wyprowadzić funkcję składową klasy bazowej, i zapewnić ich wdrożenie w klasie pochodnej:

class A { 
public: 
    int foo; 
    virtual char get_bar() = 0; 
}; 

class B : public A { 
    char bar; 
public: 
    char get_bar() { 
     return bar; 
    } 
}; 
+0

Sposób, w jaki zaprojektowałem swój algorytm, zawsze będę wiedział, kiedy wskaźnik wskazuje na klasę pochodną. To działa idealnie na to, czego potrzebuję. Próbowałem dynamicznej obsady, ale nie myślałem o robieniu statycznej obsady, dziękuję. Zaznaczam to jako odpowiedź. – Stephen

+0

Zaakceptowałeś odpowiedź z niewłaściwych powodów. Powinieneś poważnie rozważyć użycie funkcji wirtualnej. –

+0

To pytanie dotyczyło jednego programu, z którego większość została już napisana. Potrzebowałem tej konkretnej odpowiedzi jako szybkiej poprawki. W przyszłości zdecydowanie skorzystam z funkcji wirtualnych, aby wykonać zadanie. – Stephen

0

W przypadku kodu, twój członek klasy pochodnej jest prywatny. Nie można uzyskać do niego dostępu z klasy bazowej. Jeśli chcesz uzyskać dostęp, musisz zmienić element klasy pochodnej na "publiczny". Należy naprawić swój kod tak:

class B : public A { 
public: 
    char bar; 
}; 

int main() { 
A * arr[5]; 
arr[0] = new B; 

char test = static_cast <B *>(arr[0])->bar; //visual studio highlights this with an error "class A has no member bar" 
return 0; 

}

1

Przeczytaj o type-casting, jest to bardzo proste i ważnym aspektem języka.

W skrócie, zawsze można rzucić wskaźnik na bazę do wskaźnika na pochodną, ​​a następnie odwołać się do jego unikatowych członków publicznych.

A * arr[5]; 
arr[0] = new B; 

char test = static_cast<B*>(arr[0])->bar; 

Jednak ostatnia linia powyżej jest ważne stwierdzenie, że nawet jeśli A* naprawdę nie wskazują na przedmiot B typu. Jeśli spróbujesz tego na obiekcie C, zostanie skompilowany i spowoduje nieokreślone zachowanie w czasie wykonywania.

Należy jednak wspomnieć, że zazwyczaj, gdy nie można mieć pewności co do typu obiektu, do którego się odnosi, lepszy projekt programu mógł temu zapobiec. Powszechnie twierdzi się, że dotyczy to ogólnie odlewania typów.

P.S. Zauważ, że w twoim kodzie, bar jest prywatnym członkiem class B (niechcący przypuszczam, że każdy członek class jest domyślnie prywatny), więc nie można uzyskać do niego dostępu poza implementacją class B.

+0

Rzucanie nie jest właściwym narzędziem do wykonania zadania i nie jest to podstawowy aspekt, jeśli chodzi o paradygmat programowania obiektowego, który jest ważniejszy niż jakikolwiek inny język. Proszę nie używać odlewania, aby zatuszować nieodpowiednią konstrukcję OO. –

+0

Uważam, że jest to dyskusyjne. I dla mnie to pytanie nie dotyczyło OOD. Było to pytanie techniczne, a odlewanie typu jest prostą odpowiedzią na pytanie w sposobie, w jaki zostało utworzone. Jeśli znasz "odpowiednie narzędzie do pracy", które nie zmienia tematu, proszę. –

+0

"Wierzę, że to jest dyskusyjne". Ja nie. "To było pytanie techniczne". To było pytanie kogoś, kto potrzebuje wskazówek, a nie poprawnych technicznie, ale niebezpiecznych odpowiedzi. –