Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 13.05.2010, 20:51   #1
katbka
Пользователь
 
Регистрация: 06.09.2008
Сообщений: 17
По умолчанию Полиморфизм. Как реализовать вызов метода?

Есть класс-предок. У него несколько классов потомков.
Создается массив типа "предок", в котором находятся также объекты типа "потомок".
Необходимо ко всему массиву применить метод, который должен работать по-разному в зависимости от типа потомка.
Как написать? У разных потомках в сигнатуре метода разное количество параметров.
Класс предок не абстрактный. Объекты типа предок тоже должны быть в массиве.
Метод, который необходимо применить ко всему массиву в общем то нужен только в двух классах потомках.
Подскажите как это реализовать?
Если просто переопределять метод в потомках, а потом в зависимости от типа объекта в массиве вызывать метод с определенным количеством параметров, компиллятор ругается...
Error 1 No overload for method 'move' takes '6' arguments C:\Users\1\Desktop\Ocean\Ocean\Main Form.cs 120 29 Ocean

Move и есть тот самый метод. Не понимаю почему эта ошибка возникает... аргументов везде хватает...


Заранее спасибо большое...
katbka вне форума Ответить с цитированием
Старый 13.05.2010, 21:20   #2
profi
Участник клуба Подтвердите свой е-майл
 
Регистрация: 19.11.2007
Сообщений: 1,022
По умолчанию

Вот тебе пример полиморфизма:
Цитата:
#include <iostream.h>

class A
{
public:
virtual char* move(){
return "A::move";
}
};

class B: public A
{
char* move(){
return "B::move";
}
};

class C: public A
{
char* move(){
return "C::move";
}
};

int main()
{
A* mas[3];
A a;
B b;
C c;
mas[0] = &a;
mas[1] = &b;
mas[2] = &c;

for(int i = 0; i < 3; i++)
cout << mas[i]->move() << "\n";

return 0;
}
Цитата:
У разных потомках в сигнатуре метода разное количество параметров.
Это уже не полиморфизм.

Последний раз редактировалось profi; 13.05.2010 в 21:28.
profi вне форума Ответить с цитированием
Старый 13.05.2010, 21:28   #3
katbka
Пользователь
 
Регистрация: 06.09.2008
Сообщений: 17
По умолчанию

Это все понимаю...
а если возвращаемых значений несколько?
тогда как метод описывать? По идее пишу также... а ошибочка...
public void move(...., ref a)
просто у меня так... как написать правильно?
katbka вне форума Ответить с цитированием
Старый 13.05.2010, 21:31   #4
profi
Участник клуба Подтвердите свой е-майл
 
Регистрация: 19.11.2007
Сообщений: 1,022
По умолчанию

Цитата:
а если возвращаемых значений несколько?
Как?
Цитата:
public void move(...., ref a)
просто у меня так... как написать правильно?
От куда я знаю. Я дал пример полиморфизма. Не знаю, что там еще хочешь сделать .
profi вне форума Ответить с цитированием
Старый 13.05.2010, 21:35   #5
netrino
Участник клуба
 
Аватар для netrino
 
Регистрация: 15.07.2008
Сообщений: 1,933
По умолчанию

Думаю полиморфизм тут ни при чём. Неплохо бы увидеть ваш код и более конкретные пояснения цели всего этого, возможно это можно сделать как-то проще. Тем не менее, если я вас верно понял, то можно использовать рефлексию для получения информации о том, с объектом какого класса мы имеем дело, приводить его к этому классу и вызывать его метод.
netrino вне форума Ответить с цитированием
Старый 13.05.2010, 21:50   #6
katbka
Пользователь
 
Регистрация: 06.09.2008
Сообщений: 17
По умолчанию

Цитата:
Сообщение от netrino Посмотреть сообщение
Думаю полиморфизм тут ни при чём. Неплохо бы увидеть ваш код и более конкретные пояснения цели всего этого, возможно это можно сделать как-то проще. Тем не менее, если я вас верно понял, то можно использовать рефлексию для получения информации о том, с объектом какого класса мы имеем дело, приводить его к этому классу и вызывать его метод.
в общем... должны быть 3 класса: хищники, жертвы и преграды. Чтоб их хранить вместе создала класс океан, который является их общим предком.
Массив типа океан.
Хищники и преграды должны перемещаться(меняться координаты в массиве), для этого написан метод move, где все в принципе прописано.
С вызовом метода проблема...
Код:
public class oceanSpace
    {
        public void move()
        { }
    }

public class predator: oceanSpace
    {
        private string name;
        private int lifeReserve;
        private int periodSelfReproduction;
        private bool step;
 public void move(oceanSpace[,] mas, int n, ref int a, ref int b, int LR, int iterNumb)
        {....}
}
public class booty: oceanSpace
    {
        private string name;
        private int lifeReserve;
        private int periodSelfReproduction;
        private bool step;

public void move(oceanSpace[,] mas, int n, ref int a, ref int b, int iterNumb)
        {....}
}

 public class barrier: oceanSpace
    {
    }

Создается массив oceanMatr

Код:
if (oceanMatr[i, j].GetType().ToString() == "Ocean.predator")
                        {
                            oceanMatr[i, j].move(oceanMatr, n, ref a, ref b,        Demo.lRofP, iter);
                        }
вот собственно попытка вызвать его...
ткните пожалуйста в ошибку...
katbka вне форума Ответить с цитированием
Старый 13.05.2010, 22:20   #7
netrino
Участник клуба
 
Аватар для netrino
 
Регистрация: 15.07.2008
Сообщений: 1,933
По умолчанию

Мда, с абстракциями не очень вышло ) Едва ли океан можно назвать предком хищника ) Если подобная реализация была вызвана необходимостью передавать всё одним массивом, то в этом нет необходимости, так как у всех классов есть один общий предок - Object. Можно создать массив object'ов и класть туда объекты совершенно разных классов. Кстати, вместо
Код:
oceanMatr[i, j].GetType().ToString() == "Ocean.predator"
проще использовать оператор is )
Код:
if(oceanMatr[i, j] is predator)
В общем случае то, о чём я говорил, может выглядеть так:
Код:
class ClassZero {
    public int ClassZeroFunction(int a) {
        return a + 1;
    }
}
 
class ClassOne {
    public int ClassOneFunction(int a, int b) {
        return b + a;
    }
}
 
class ClassTwo {
    public int ClassTwoFunction(int a, int b, int c) {
        return a + b + c;
    }
}
 
class MainClass {
    public static void Main(string[] args) {
        object[] arr = { new ClassZero(), new ClassOne(), new ClassTwo() };
        
        foreach(object o in arr)
            System.Console.WriteLine("Result = {0}", Calc(o));
    }
 
    public static int Calc(object p) {
        int result = 0;
 
        if (p is ClassOne)
            result = ((ClassOne)p).ClassOneFunction(10, 20);
        else if (p is ClassTwo)
            result = ((ClassTwo)p).ClassTwoFunction(10, 20, 30);
        else if (p is ClassZero)
            result = ((ClassZero)p).ClassZeroFunction(10);
 
        return result;
    }
}
netrino вне форума Ответить с цитированием
Старый 13.05.2010, 22:28   #8
katbka
Пользователь
 
Регистрация: 06.09.2008
Сообщений: 17
По умолчанию

ааа спасибо огромное вам=))
katbka вне форума Ответить с цитированием
Старый 13.05.2010, 23:44   #9
katbka
Пользователь
 
Регистрация: 06.09.2008
Сообщений: 17
По умолчанию

Цитата:
Сообщение от netrino Посмотреть сообщение
Мда, с абстракциями не очень вышло ) Едва ли океан можно назвать предком хищника ) Если подобная реализация была вызвана необходимостью передавать всё одним массивом, то в этом нет необходимости, так как у всех классов есть один общий предок - Object. Можно создать массив object'ов и класть туда объекты совершенно разных классов. Кстати, вместо
Код:
oceanMatr[i, j].GetType().ToString() == "Ocean.predator"
проще использовать оператор is )
Код:
if(oceanMatr[i, j] is predator)
В общем случае то, о чём я говорил, может выглядеть так:
Код:
class ClassZero {
    public int ClassZeroFunction(int a) {
        return a + 1;
    }
}
 
class ClassOne {
    public int ClassOneFunction(int a, int b) {
        return b + a;
    }
}
 
class ClassTwo {
    public int ClassTwoFunction(int a, int b, int c) {
        return a + b + c;
    }
}
 
class MainClass {
    public static void Main(string[] args) {
        object[] arr = { new ClassZero(), new ClassOne(), new ClassTwo() };
        
        foreach(object o in arr)
            System.Console.WriteLine("Result = {0}", Calc(o));
    }
 
    public static int Calc(object p) {
        int result = 0;
 
        if (p is ClassOne)
            result = ((ClassOne)p).ClassOneFunction(10, 20);
        else if (p is ClassTwo)
            result = ((ClassTwo)p).ClassTwoFunction(10, 20, 30);
        else if (p is ClassZero)
            result = ((ClassZero)p).ClassZeroFunction(10);
 
        return result;
    }
}

Error 1 'object' does not contain a definition for 'move' C:\Users\Кэт\Desktop\Ocean\Ocean\Ma inForm.cs 120 45 Ocean

не подскажите в чем сейчас моя ошибка?)
katbka вне форума Ответить с цитированием
Старый 13.05.2010, 23:50   #10
netrino
Участник клуба
 
Аватар для netrino
 
Регистрация: 15.07.2008
Сообщений: 1,933
По умолчанию

А тип, как у меня, приводите? )
Код:
((ClassOne)p).ClassOneFunction(10, 20);
Сам по себе object конечно же не имеет и ничего не знает о методе move, о нём знает класс predator. Потому необходимо сначала привести object к этому классу и только тогда уже вызывать метод. Главное перед этим убедиться, что объект относится к классу predator
netrino вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Необязательные параметры метода -как? boris-blade Общие вопросы .NET 2 24.03.2010 03:42
Вызов метода в asm вставке. Mixasik Общие вопросы Delphi 3 20.02.2010 10:42
Как определить время работы метода??? _Studentka_ Общие вопросы по Java, Java SE, Kotlin 1 22.11.2009 10:43
mootools: вызов метода класса в цикле each toXx JavaScript, Ajax 1 18.03.2009 19:20
Вызов Метода из др. модуля Mickle Общие вопросы Delphi 2 10.05.2007 23:41