서형박 Ответов: 2

<C++> У меня есть вопрос о виртуальных функциях.


#include <iostream>
#include <cstring>
#include <cstdlib>

using namespace std;

class Fir
{
public:
	virtual void mfunc() { cout << "First func" << endl; }
};

class Sec : public Fir
{
public:
	virtual void mfunc() { cout << "Second func" << endl; }
};

class Thi : public Sec
{
public:
	virtual void mfunc() { cout << "Third func" << endl; }
};

int main()
{
	Thi * tptr = new Thi();
	Sec * sptr = tptr;
	Fir * fptr = sptr;

	fptr->mfunc();
	sptr->mfunc();
	tptr->mfunc();
	delete tptr;
	return 0;
}


Что я уже пробовал:

Когда я выполняю приведенный выше код, "третья функция" отображается три раза. Мне интересно, почему результатом " fptr->mfunc()" является "третий func" вместо "второго func", хотя он указывает на объект Sec.

2 Ответов

Рейтинг:
9

CPallini

В этом и заключается цель виртуальных функций: разрешить полиморфизм.
Рассмотрим, например, следующий код

void draw_shapes( Shape * sh[], size_t count)
{
  for ( size_t n = 0; n < count; ++n)
    sh[n]->draw_myself();
}

каждый элемент массива (каждый Shape) нарисует себя в зависимости от своей реальной природы: а Circle и Rectangle например, будут получаться совсем другие рисунки.

[Обновление]
Цитата:
Есть еще немного запутанная часть. Отношение наследования текущих классов - "Fir <- Sec <- Thi". Если виртуальная функция вызывается, является ли функция mFunc () класса thi последней переопределенной, так что один и тот же результат выводится все три раза?


Каждый объект выполняет свои функции mfunc код, даже если объявление указателя указывает базовый класс. Попробуй:
int main()
{
  Fir * p[] = { new Fir(), new Sec(), new Thi()};

  for ( size_t n = 0; n < 3; ++n)
    p[n]->mfunc();

  for ( size_t n = 0; n < 3; ++n)
    delete p[n];
  
  return 0;
}
[/Обновление]


서형박

Есть еще немного запутанная часть. Отношение наследования текущих классов - "Fir <- Sec <- Thi". Если виртуальная функция вызывается, является ли функция mFunc () класса thi последней переопределенной, так что один и тот же результат выводится все три раза?

CPallini

Смотрите мое обновленное решение.

서형박

Огромное спасибо :)

CPallini

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

Рейтинг:
0

Gerry Schmitz

Виртуальные методы используются "как есть"; или вы "переопределяете" их; вы не сделали ни того, ни другого; вы просто создали виртуальный метод "замены" в каждом классе.

Пытаться "забросить вниз" в этой ситуации не имеет смысла.