Что именно означает полиморфизм во время выполнения? - PullRequest
2 голосов
/ 11 августа 2010

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

Возьмите этот пример:

class a
{
a();
~a();
void baseclass();
}

class b: class a
{
b();
~b();
void derivedclass1();
}

class c: class a
{
c();
~c();
void derivedclass2();
}

Методология вызова:

b derived1;
a *baseptr = &derived1; //here base pointer knows that i'm pointing to derived class b. 
baseptr->derivedclass1();

В приведенной выше методологии вызова базовый класс знает, что он указывает на производный класс b.

Так, где существует неоднозначность?

В каких случаях определения функций получатразрешается во время выполнения?

Ответы [ 6 ]

10 голосов
/ 11 августа 2010

Этот код во время выполнения вызывает правильную версию f () в зависимости от типа объекта (A или B), который был фактически создан - никакой «двусмысленности».Тип не может быть известен во время компиляции, поскольку он выбирается случайным образом во время выполнения.

struct A {
   virtual ~A() {}
   virtual void f() {}
};

struct B : public A {
   virtual void f() {}
};


int main() {
   A * a = 0;
   if ( rand() % 2 ) {
      a = new A;
   }
   else {
      a = new B;
   } 
   a->f();   // calls correct f()
   delete a;
}
5 голосов
/ 11 августа 2010

В приведенном примере нет двусмысленности.

Если базовый класс имеет то же имя функции, что и производный класс, и если вы вызываете его указанным способом, он вызовет функцию базового класса вместо производного класса.

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

Здесь вы можете найти больше объяснений ..

1 голос
/ 11 августа 2010

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


class BaseClass
{
public:
  virtual void method() {...};
};

class DerivedClassA : public BaseClass
{
  virtual void method() {...};
};

class DerivedClassB : public BaseClass
{
  virtual void method() {...};
};

void func(BaseClass* a)
{
  a->method();
}

Когда вы реализуете :: func (), вы не знаете точно тип экземпляра, на который указывает BaseClass * a. Это может быть экземпляр DerivedClassA или DerivedClassB и т. Д.
Вы должны понимать, что полиморфизм во время выполнения требует специальной поддержки языка (и, возможно, некоторых накладных расходов для вызова «виртуальных» функций). В C ++ вы «запрашиваете» динамический полиморфизм, объявляя методы базового класса «virtual» и используя публичное наследование.

1 голос
/ 11 августа 2010

Преврати это

void baseclass();

до

virtual void baseclass();

Переопределите это в ваших производных классах b и c. Тогда

b *derived1 = new derived1 ();
a *baseptr = derived1; //base pointer pointing to derived class b. 
baseptr->baseclass();

вызовет определение производного1, выражающее полиморфизм времени выполнения. И помните о том, чтобы сделать ваш деструктор виртуальным в базе. Некоторые базовые материалы для чтения полиморфизма

0 голосов
/ 02 мая 2013

Давайте проведем эксперимент

#include <iostream>
using namespace std;
class aBaseClass
{

public:

    void testFunction(){cout<<"hello base";}///Not declared as virtual!!!!

};
class aDerivedClass:public aBaseClass
{
public:
    void testFunction(){cout<<"hello derived one";}
};

class anotherDerivedClass:public aDerivedClass
{
public:
    void testFunction(){cout<<"hello derived two";}

};
int main()
{
    aBaseClass *aBaseClassPointer;
    aBaseClassPointer=new aDerivedClass;
    aBaseClassPointer->testFunction();
}

Приведенный выше код не поддерживает полиморфизм во время выполнения.Давайте запустим и проанализируем это.Выходное значение равно

hello base

Просто измените строку void testFunction(){cout<<"hello base";} на virtual void testFunction(){cout<<"hello base";} в aBaseClass.Запустите и проанализируйте это.Мы видим, что во время выполнения полиморфизм достигнут.Вызов соответствующей функции определяется во время выполнения.

Снова измените строку aBaseClassPointer=new aDerivedClass на aBaseClassPointer=new anotherDerivedClass в основной функции и посмотрите результат.Таким образом, соответствующий вызов функции определяется во время выполнения (когда программа запущена).

0 голосов
/ 11 августа 2010

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

 a->someMethod();

Теперь указатель может указывать на экземпляр любого из производных классов, и поэтому тип того, на что указывает объект, должен определять, какой метод someMethod () вызывается.

...