Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Перегрузка виртуальных функций, есть ли? 
V
    Опции темы
gamedeveloper
Дата 2.6.2008, 22:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 42
Регистрация: 8.7.2007

Репутация: нет
Всего: нет



Можно ли на С++ перегрузить виртуальную функцию в классе наследнике?

Код не рабочий, но думаю идея ясна.
Код

class SuperClass {
public:
        virtual void memfunc(char *str)=0;
};

class SubClass : SuperClass {
public:
        void memfunc(double d) {
                
        }
}

PM MAIL   Вверх
Fazil6
Дата 2.6.2008, 22:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1653
Регистрация: 3.5.2006
Где: Минск

Репутация: 35
Всего: 60



ну в общем случае можно, только спрашивается для чего?
PM MAIL   Вверх
Lazin
Дата 2.6.2008, 22:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



Цитата(gamedeveloper @  2.6.2008,  22:29 Найти цитируемый пост)
думаю идея ясна

никак нет, абсолютно не ясна smile
вот это
Код

void memfunc(double d)

уже не виртуальная фунция, к тому-же SuperClass о ней ничего не знает, так что я затрудняюсь ответить как это может быть использовано...
PM MAIL Skype GTalk   Вверх
gamedeveloper
Дата 2.6.2008, 23:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 42
Регистрация: 8.7.2007

Репутация: нет
Всего: нет



Если идея не ясна, тогда так:

Есть базовый клас SuperClass. В нём есть виртуальная функция memfunc с входным параметром типа char*.
Есть наследник базового класса SubClass. В нём есть унаследованная виртуальная функция memfunc, НО уже с входным параметром double.
Такое может быть на Си++?

То есть можно ли перегрузить при наследовании виртуальную функцию?
PM MAIL   Вверх
baldina
Дата 2.6.2008, 23:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



нельзя. и не нужно:
Код

SuperClass *p = new SubClass;

p->memfunc (1.0); // error: нет функции SuperClass::memfunc (double);
p->memfunc ("text"); // что должно быть вызвано?

у тебя явно какая-то задача, имеющая другое (возможно, очень простое) решение

Это сообщение отредактировал(а) baldina - 2.6.2008, 23:08
PM MAIL   Вверх
gamedeveloper
Дата 2.6.2008, 23:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 42
Регистрация: 8.7.2007

Репутация: нет
Всего: нет



Задачи как таковой нет. Просто с другом о языках спорим. Вот он и завёл тему про перегрузку виртуальных функций в иерархии. Я пробовал сделать, но компилятор и линкер по очереди ругались, то нельзя создать экземпляр абстрактного класса, то в SuperClass нет void memfunc(double).
Вот и решил у более обознаных людей спросить.

Я пока тему не снимаю, может у кого то ещё есть мнение...

Это сообщение отредактировал(а) gamedeveloper - 2.6.2008, 23:24
PM MAIL   Вверх
opjox
Дата 3.6.2008, 01:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 90
Регистрация: 17.1.2008

Репутация: 1
Всего: 14



Можно перегрузить. Однако, чтобы создать экземпляр SubClass надо в нем все таки определить memfunc(char *str). Также в предложенном коде есть неточность – функция memfunc(double d) не будет виртуальной, это можно наглядно понять из этого кода (этот код аналогичен первичному, за исключением необходимо определенной memfunc(char *str) ):

Код

#include <iostream>

class A {
public:
  virtual void memfunc(char *str) = 0;
};

class B: public A {
public:
  void memfunc(double d)  // это не виртуальная функция
  {
    std::cout << "memfunc(double d): B" << std::endl;
  }

  void memfunc(char *str) // чтобы создать экземпляр этого класса, надо определить эту функцию
  {
    std::cout << "memfunc(char *str): B" << std::endl;
  }
};

class C: public B {
public:
  void memfunc(char *str)
  {
    std::cout << "memfunc(char *str): C" << std::endl;
  }

  void memfunc(double d)
  {
    std::cout << "memfunc(double d): C" << std::endl;
  }
};

int main()   
{  
  A *a;
  B  b;
  C  c;
  
  a = &b;
  a->memfunc(0);

  a = &c;
  a->memfunc(0);

  B *p;
  p = &b;
  p->memfunc(0.);
  p = &c;
  p->memfunc(0.); // указатель имеет тип B, поэтому будет вызвана функция B::memfunc(double d)

  return 0;   
}


Предполагаю, что в итоге хотелось увидеть примерно это (вариант перегрузки виртуальной функции в классе-наследнике):

Код

#include <iostream>

class A {
public:
  virtual void memfunc(char *str)
  {
    std::cout << "memfunc(char *str)::A" << std::endl;
  }

  virtual void memfunc(double d)
  {
    std::cout << "memfunc(double d)::A" << std::endl;
  }
};

struct ST {char bb;};

class B: public A {
public:
  virtual void memfunc(ST bb) // перегружаем, ключевое слово virtual здесь необходимо
  {
    std::cout << "memfunc(ST bb)::B" << std::endl;
  }

  void memfunc(double d)      // переопределяем
  {
    std::cout << "memfunc(double d)::B" << std::endl;
  }
};

class C: public B {
public:
  void memfunc(char *str)     // переопределяем
  {
    std::cout << "memfunc(char *str)::C" << std::endl;
  }

  void memfunc(double d)      // переопределяем
  {
    std::cout << "memfunc(double d)::C" << std::endl;
  }

  void memfunc(ST bb)         // переопределяем
  {
    std::cout << "memfunc(ST bb)::C" << std::endl;
  }
};

int main()
{
  A a, *pa;
  B b, *pb;
  C c;
  ST s;

  pa = &a;
  pa->memfunc((char *)0);
  pa->memfunc(0.);

  std::cout << std::endl;

  pa = pb = &b;
  pa->memfunc((char *)0); // она не была переопределена в производном классе
  pa->memfunc(0.);
  pb->memfunc(s);         // pa нельзя использовать, т.к. он ничего не знает о memfunc(ST bb)
  
  std::cout << std::endl;

  pa = pb = &c;
  pa->memfunc((char *)0);
  pa->memfunc(0.);
  pb->memfunc(s);
  return 0;
}


PM MAIL ICQ   Вверх
georain
Дата 3.6.2008, 01:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 193
Регистрация: 28.11.2006
Где: Санкт-Петербург

Репутация: нет
Всего: нет



gamedeveloper, нужно различать статическое и динамическое связывание. Когда виртуальная функция переопределяется, то при её вызове происходит поиск конкретной реализации в зависимости от вызывающего класса (во время выполнения). А когда виртуальная функция перегружается то поиск производится по типу аргументов (во время компиляции) и смысл виртуальности пропадает.
PM MAIL   Вверх
opjox
Дата 3.6.2008, 02:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 90
Регистрация: 17.1.2008

Репутация: 1
Всего: 14



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

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



P.S. или мне опять нужно больше спать? smile 

PM MAIL ICQ   Вверх
baldina
Дата 3.6.2008, 09:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



georain и opjox правы оба, только говорят чуть о разном. Тут и то и другое - во время компиляции выбирается сигнатура функции, во время выполнения (если данная сигнатура определила виртуальную функцию) происходит поиск функии по таблице.
Все может иметь место одновременно.
Можно представить это таким образом: виртуальная функция определяет набор поведений объектов различных типов в одной иерархии (скажем, функция draw() в иерархии графических примитивов), а перегруженная - набор однотипных операций по различным входным данным (например, функции MessageBox (UINT RscId) и MessageBox (const char* message))

gamedeveloper, возможности языка не возникают на пустом месте. Есть конкретные задачи, для них - конкретные решения в языке. Есть вещи, напрямую языком не поддерживаемые. Например, мультиметоды не поддерживаются С++ - они как раз близки к обсуждаемой теме.
PM MAIL   Вверх
Alek86
Дата 3.6.2008, 09:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1299
Регистрация: 30.1.2007
Где: Киев

Репутация: 21
Всего: 25



Код

class SuperClass {
public:
 virtual void memfunc(char *str);
};

class SubClass : SuperClass {
public:
 using SuperClass::memfunc;
 void memfunc(double d) {}
};



--------------------
user posted image    user posted image
PM MAIL   Вверх
georain
Дата 3.6.2008, 14:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 193
Регистрация: 28.11.2006
Где: Санкт-Петербург

Репутация: нет
Всего: нет



Согласен opjox более правильно изложил smile
PM MAIL   Вверх
gamedeveloper
Дата 5.6.2008, 22:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 42
Регистрация: 8.7.2007

Репутация: нет
Всего: нет



Всем спасибо.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0992 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.