Как определить, на какой производный класс указывать при использовании массива указателей - PullRequest
6 голосов
/ 23 июля 2010

Я пишу программу на C ++, которая бросает кубик и подбрасывает монету. Мне нужно использовать наследование и полиморфизм. Мои виртуальные функции настроены правильно. В моем базовом классе (aRandomNumberGenerator) у меня есть виртуальная функция Generate. В main () мне нужно иметь массив из 2 указателей базовых классов на мои производные классы (aDie и aCoin). Как узнать, на какой производный класс указывается в массиве, когда я вызываю функцию generate () ??

код:

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 ]

8 голосов
/ 23 июля 2010

Использовать dynamic_cast.

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

Однако для обычного вызова метода вам не нужно его определять.Просто вызовите метод базового класса, и он будет отправлен в правильный производный класс - вот для чего нужно наследование.

Редактировать: Для обычного виртуального метода вы можете просто вызватьэто на базовом указателе, и вы не знаете, что это за производное, и вы получите правильный вызов функции.

3 голосов
/ 23 июля 2010
aRandomNumberGenerator *games[2]; // array of 2 base class pointers 

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

Во-первых, давайте работать, прежде чем мы займемся другими вещами.

Вы создаете массив, который будет содержать указатели на два объекта aRandomNumberGenerator, но вы никогда не создадите сами объекты aRandomNumberGenerator. games[0] и games[1] содержат бессмысленные значения. Кроме того, в цикле вы также получаете доступ к games[2], который не существует.

UPDATE: По какой-то причине другой ответчик решил использовать причудливую сокращенную версию кода, которую я ненавижу, и, вероятно, запутал бы любой неопытный код C ++ (который явно является ОП), поэтому давайте сделаем это сами:

Derived1* ptr = dynamic_cast<Derived1*>(basepointer)
if (ptr != null) 
{ 
    // Do something with ptr 
} 
0 голосов
/ 23 июля 2010

Вы можете использовать RTTI (typeid и dynamic_cast) или добавить виртуальную функцию, которая в реализации идентифицирует класс (переход на ваш собственный RTTI).

Как правило, если вы можете избежать этого, добавление кода, зависящего от реализации (кода, который заботится о точном типе), считается плохой практикой, за исключением самой реализации. Под «реализацией» я имею в виду не только конкретный класс производных, но и парные / связанные классы, специфичные для этой реализации.

Попытайтесь свернуть операторы switch / else-if, которые специфичны для ваших точных реализаций, в самих реализациях посредством полиморфизма.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...