Вопрос о виртуальных методах - PullRequest
4 голосов
/ 06 мая 2010

ЕСЛИ оба метода объявлены как виртуальные, не должны ли оба экземпляра Method1 (), которые вызываются, быть Method1 () производного класса?

Я вижу BASE, затем каждый раз вызывается DERIVED. Я делаю некоторый обзор для интервью, и я хочу убедиться, что у меня есть это прямо. XD

class BaseClass
{
public:
    virtual void Method1()  { cout << "Method 1 BASE" << endl; }
};

class DerClass: public BaseClass
{
public:
    virtual void Method1() { cout << "Method 1 DERVIED" << endl; }
};


DerClass myClass;
    ((BaseClass)myClass).Method1();
    myClass.Method1();

Метод 1 БАЗА
Метод 1 из 3:

Ответы [ 5 ]

14 голосов
/ 06 мая 2010

Нет, приведение в стиле C ((BaseClass)myClass) создает временный объект BaseClass путем нарезки myClass. Его динамический тип - BaseClass, это вовсе не DerClass, поэтому вызываемый Method1 является методом базового класса.

myClass.Method1() это прямой звонок. Поскольку myClass является объектом, а не ссылкой, нет виртуальной отправки (в этом не было бы необходимости).

12 голосов
/ 06 мая 2010

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

6 голосов
/ 06 мая 2010

То, что вы видите здесь, называется "нарезка" . Приведение объекта производного класса к базовому классу «отрезает» все, что не находится в базовом классе.

В C ++ виртуальные функции работают корректно только для указателей или ссылок. Чтобы ваш пример работал правильно, вы должны сделать следующее:

<code>
DerClass myClass;
((BaseClass *) &myClass)->Method1();

Или вы могли бы сделать


BaseClass *pBase = new DerClass;
pBase->Method1();

5 голосов
/ 06 мая 2010

Поскольку приведение ((BaseClass)myClass) разрезает объект myClass с DerClass до BaseClass, поэтому вызывается только реализация BaseClass Method1().

Чтобы полиморфизм работал правильно, вы должны вызывать методы через указатели:

DerClass myClass; 
BaseClass* ptrToMyClass = &myClass;
ptrToMyClass->Method1(); // Calls the DerClass implementation of Method1()

или ссылки:

DerClass myClass; 
BaseClass& refToMyClass = myClass;
refToMyClass.Method1();  // Calls the DerClass implementation of Method1()
0 голосов
/ 29 января 2015

((BaseClass) MyClass) .Method1 (); -> нарезка объекта, следовательно, всегда вызывается метод базового класса. Реальное полиморфное поведение достигается с помощью указателя базового класса, который может содержать любые объекты производных классов. Следовательно, чтобы достичь желаемого, вам нужно передать адрес объекта производного класса и типизировать его в указатель базового класса. как показано ниже: ((BaseClass *) & myClass) -> Method1 ();

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