Какие функции должны быть виртуальными для вывода определенных элементов? - PullRequest
0 голосов
/ 13 декабря 2010

Я пытаюсь вывести следующее:

apple
banana
orange
banana

Нужно ли делать виртуальные функции для вывода?

class Red
{
public:
    void PrintMe() { Foo(); Bar(); }
    void Foo() { printf("pear\n"); }
    void Bar() { printf("lemon\n"); }
};

class Green : public Red
{
public:
    void PrintMe() { Bar (); Foo(); }
    void Foo() { printf("apple\n"); }
    void Bar() { printf("banana\n"); }
};

class Blue : public Green
{
public:
    void Foo() { printf("orange\n"); }
    void Bar() { printf("grape\n"); }
};
int main(int argc, char* argv[])
{
    Green g;
    Blue b;

    Red *pR1 = &g;
    Red *pR2 = &b;
    pR1->PrintMe();
    pR2->PrintMe();
}

Ответы [ 6 ]

2 голосов
/ 13 декабря 2010

Нет способа получить «яблочный банан, оранжевый банан» в качестве выходных данных с вашей текущей настройкой, потому что:

  1. Чтобы напечатать «яблочный банан» с помощью Red *pR1, вы должны сделать Foo и Bar virtual.
  2. Как только вы объявите функцию как виртуальную, она останется такой же во всех производных классах.
  3. Теперь, поскольку Bar является виртуальным, pR2->PrintMe() будет печатать "апельсиновый виноград "- нет никакой возможности напечатать" банан ".
0 голосов
/ 13 декабря 2010

LOL!Никто не понял это правильно!

Вам нужно сделать PrintMe виртуальным, потому что порядок foo / bar может измениться.

Вам нужно сделать Foo и Bar виртуальными, потому что они делают разные вещи.1005 *

Вам нужно сделать DESTRUCTOR виртуальным, потому что вы реализуете полиморфную высшую иерархию.Этого даже нет в вашем коде.Вашему конкретному тесту main() он не нужен, но наиболее разумное, нетривиальное использование будет.

Редактировать: ОК, возможно, я тоже ошибся.Если вы не хотите, чтобы PrintMe фактически переопределял поведение при использовании через базовый указатель, тогда он НЕ должен быть виртуальным.Ваш код немного сбивает с толку.Никто бы так не поступил.

0 голосов
/ 13 декабря 2010

Краткий ответ: PrintMe () должен быть виртуальным.

Пояснение:

Поскольку вы хотите вызвать метод специализированного объекта, на который указывает указатель базового класса, вам нужно сделать этот метод виртуальным.

// Base class pointer pointing to specialized class
Red *pR1 = new Green();

// If PrintMe() is not virtual, this call will be Red::PrintMe(). 
// If you want to call Green::PrintMe, make it virtual.
pR1->PrintMe();
0 голосов
/ 13 декабря 2010

Кажется, с вашим кодом есть некоторые проблемы: вы определяете класс с именем красный , но затем Зеленый наследуется от класса с именем Красный

В любом случае, если красный является вашим базовым классом, и вы хотите, чтобы другие классы переопределяли его методы, вам нужно объявить их virtual в самом деле.

0 голосов
/ 13 декабря 2010

Red::Foo() и Red::Bar() должны быть виртуальными.

0 голосов
/ 13 декабря 2010

Да, в противном случае вы печатаете два красных.

...