Полиморфизм С ++ - PullRequest
       26

Полиморфизм С ++

3 голосов
/ 03 июня 2011

Я хотел бы напечатать мой код:

B B
A B
B A

Но он печатает

Item Item
Item Item
Item Item

Код:

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;

struct Item {
    Item(){}
    virtual void method1 (Item x, Item y) {cout << "Item Item\n";}
};

struct A : public Item {
    A(){}
};

struct B : public Item {
    B(){}
    virtual void method1 (B x, B y) {cout << "B B\n";}
    virtual void method1 (A x, B y) {cout << "A B\n";}
    virtual void method1 (B x, A y) {cout << "B A\n";}
};

int main ( void ) {
    Item * a[2];
    a[0] = new B; a[1] = new A;
    a[0]->method1(*a[0], *a[0]);
    a[0]->method1(*a[1], *a[0]);
    a[0]->method1(*a[0], *a[1]);
}

Ответы [ 5 ]

5 голосов
/ 03 июня 2011

Вы не переопределяете method1 с соответствующими параметрами, поэтому он продолжает вызывать method1 в Item классе.

Item * a[2];

Итак *a[0] & *a[1] оба имеют тип Item. Это вызывает ваши звонки:

a[0]->method1(*a[0], *a[0]);
a[0]->method1(*a[1], *a[0]);
a[0]->method1(*a[0], *a[1]);

как вызовы method1(Type,Type), который определен в базовом Item классе.
Вы должны переопределить этот метод с помощью same parameters в своих дочерних классах, чтобы иметь возможность вызывать методы в дочернем классе.

Вот что, я думаю, вы пытаетесь сделать:

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;

struct Item {
    Item(){}
    virtual void method1 (Item x, Item y) {cout << "Item Item\n";}
    virtual void method2 (Item x, Item y) {cout << "Item Item\n";}
    virtual void method3 (Item x, Item y) {cout << "Item Item\n";}
};

struct A : public Item {
    A(){}
};

struct B : public Item {
    B(){}
    virtual void method1 (Item x, Item y) {cout << "B B\n";}
    virtual void method2 (Item x, Item y) {cout << "A B\n";}
    virtual void method3 (Item x, Item y) {cout << "B A\n";}

};

int main ( void ) 
{
    Item * a[2];
    a[0] = new B; a[1] = new A;
    a[0]->method1(*a[0], *a[0]);
    a[0]->method2(*a[1], *a[0]);
    a[0]->method3(*a[0], *a[1]);
}

Это даст вам желаемый результат:

output:
B B
A B
B A

Здесь method1 () , method2 () & method3 () `соответствующим образом переопределены в классе Child и, следовательно, они вызываются при вызове через указатель, фактически указывающий на объект дочернего класса.

4 голосов
/ 03 июня 2011

Ваши перегрузки method1 в B не переопределяют виртуальный метод в Item. Поэтому, когда вы звоните someItem->method1, он не будет их использовать.

Похоже, вы хотите то, что называется "множественная отправка", которую C ++ не поддерживает напрямую. См. http://en.wikipedia.org/wiki/Multiple_dispatch#C.2B.2B для обсуждения и обходных путей.

4 голосов
/ 03 июня 2011

Тип a - это массив указателей на Item. Компилятор должен решить, какой метод вызывать во время компиляции, а не во время выполнения. Так как все, что он знает, это типы аргументов, которые Item, это версия, которую он вызывает.

0 голосов
/ 03 июня 2011

Вызываемая функция основана на статическом типе аргументов, а не на динамическом типе.Итак, они все Item.Вам нужна языковая функция multimethod , которой нет в C ++, но которую можно эмулировать с некоторой работой.

0 голосов
/ 03 июня 2011

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

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