2010-07-23 7 views
6

Piszę program C++, który rzuci kością i rzuci monetą. Potrzebuję użyć dziedziczenia i polimorfizmu. Mam poprawnie ustawione funkcje wirtualne. W mojej klasie bazowej (aRandomNumberGenerator) generuję funkcję wirtualną. W main() muszę mieć tablicę 2 wskaźników klasy bazowej do moich klas pochodnych (aDie i aCoin). Skąd mam wiedzieć, która klasa pochodna jest wskazywana w tablicy, gdy wywołuję funkcję generate()? KodJak ustalić, która klasa pochodna jest wskazywana przy użyciu tablicy wskaźników

:

int main() 
{ 
    int n; 
    int frequency1 = 0; // count of 1s rolled 
    int frequency2 = 0; // count of 2s rolled 
    int frequency3 = 0; // count of 3s rolled 
    int frequency4 = 0; // count of 4s rolled 
    int frequency5 = 0; // count of 5s rolled 
    int frequency6 = 0; // count of 6s rolled 
    int face; // stores most recently rolled value 
    int numHeads = 0; // count of heads 
    int numTails = 0; // count of tails 
    int side; // stores most recently flipped value 

    cout << "Enter a seed number: "; // promp for user to enter a seed number 
    cin >> n; 
    cout << endl; 
    cout << endl; 

    aRandomNumberGenerator number(n); 
    aDie die(n, n); 
    aCoin coin(n, n); 

    aRandomNumberGenerator *games[2]; // array of 2 base class pointers 

    for(int i=0; i <= 2; i++) 
     games[i]->generate(); 


    // output the seed number entered by the user 
    cout << "the seed entered is: " << die.inputSeed(n) << endl; 
    cout << endl; 
    cout << endl; 

    // summarize results for 600 flips of a coin 
    for(int counter2 = 0; counter2 < 600; counter2++) 
    { 
     side = generate(); 

     // determine flip value 0/1 and increment appropriate counter 
     switch (side) 
     { 
     case 0: 
      ++numHeads; 
      break; 
     case 1: 
      ++numTails; 
      break; 
     default: 
      cout << "can only be heads or tails"; 
     } 
    } 

    // summarize results for 600 rolls of a die 
    for(int counter1 = 0; counter1 < 600; counter1++) 
    { 
     face = generate(); 

     // determine roll value 1-6 and increment appropriate counter 
     switch (face) 
     { 
     case 1: 
      ++frequency1; 
      break; 
     case 2: 
      ++frequency2; 
      break; 
     case 3: 
      ++frequency3; 
      break; 
     case 4: 
      ++frequency4; 
      break; 
     case 5: 
      ++frequency5; 
      break; 
     case 6: 
      ++frequency6; 
      break; 
     default: 
      cout << "7 doen't exist on a die!"; 
     } 
    } 

    // output results 
    cout << "Heads: " << numHeads << endl; 
    cout << "Tails: " << numTails << endl; 
    cout << "1: " << frequency1 << endl; 
    cout << "2: " << frequency2 << endl; 
    cout << "3: " << frequency3 << endl; 
    cout << "4: " << frequency4 << endl; 
    cout << "5: " << frequency5 << endl; 
    cout << "6: " << frequency6 << endl; 

    cout << endl; 
    cout << endl; 
    system ("pause"); 
    return 0; 
+3

Polimorfizm punkt of.using całość jest, że Hou nie mają to.worry o rodzaju wcale –

Odpowiedz

8

Zastosowanie dynamic_cast.

if (Derived1* ptr = dynamic_cast<Derived1*>(basepointer)) { 
    // Do something with ptr 
} 

Jednak w przypadku zwykłego wywołania metody nie trzeba go określać. Po prostu wywołaj metodę na podstawie klasy bazowej, która zostanie wysłana do właściwej klasy pochodnej - po to jest dziedziczenie.

Edytuj: W przypadku zwykłej metody wirtualnej , możesz po prostu wywołać ją na wskaźniku bazowym i nie wiesz ani nie obchodzi, co to jest pochodna, a uzyskasz prawidłowe wywołanie funkcji.

3
aRandomNumberGenerator *games[2]; // array of 2 base class pointers 

for(int i=0; i <= 2; i++) 
    games[i]->generate(); 

Najpierw, pracujmy, zanim zajmiemy się innymi sprawami.

Tworzysz tablicę, która będzie zawierać wskaźniki do dwóch obiektów aRandomNumberGenerator, ale nigdy nie tworzysz obiektów aRandomNumberGenerator samodzielnie. games[0] i games[1] posiadają wartości bez znaczenia. Co więcej, w pętli uzyskujesz także dostęp do games[2], który nie istnieje.

AKTUALIZACJA: Z jakiegoś powodu, drugi odbierający zdecydował się użyć dziwacznej, skróconej wersji kodu, której nienawidzę, i prawdopodobnie zmyliłby niedoświadczony kod C++ (który oczywiście jest OP), więc zróbmy to sami:

Derived1* ptr = dynamic_cast<Derived1*>(basepointer) 
if (ptr != null) 
{ 
    // Do something with ptr 
} 
+0

Poprawiłem mój pętli, muszę stworzyć każdy obiekt jak normalne obiekty? a także do czego służy kod dynamic_cast? np. Gry aRandomNumberGenerator [0] = & aCoin Gry aRandomNumberGenerator [1] = & aDie – user400586

+0

Użyłem skróconej wersji, ponieważ gwarantuje to, że ptr nigdy nie będzie nadużywane, jeśli nie jest Derived1. Jeśli OP nie jest doświadczonym koderem C++, jest to dodatkowy poziom ochrony. – Puppy

0

można używać RTTI (typeid i dynamic_cast) lub dodać wirtualną funkcję, w realizacji, identyfikuje klasę (rolling własną RTTI).

Ogólnie rzecz biorąc, jeśli można tego uniknąć, za niewłaściwą praktykę uważa się dodanie kodu zależnego od implementacji (kodu, który dba o to, jaki jest dokładny typ), z wyjątkiem samej implementacji. Przez "implementację", nie mam na myśli tylko, że specyfika wywodzi się z klasy, mam na myśli także pary/powiązane klasy, które są specyficzne dla tej implementacji.

Spróbuj przekształcić instrukcje switch/else-if, które są specyficzne dla twoich konkretnych implementacji w samych implementacjach, poprzez polimorfizm.

http://www.parashift.com/c++-faq-lite/virtual-functions.html#faq-20.6

Powiązane problemy