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

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

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

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 30.07.2013, 07:52   #1
I_I_I
Пользователь
 
Регистрация: 10.12.2012
Сообщений: 17
По умолчанию Вопрос по виртуальным функциям

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

Код:
class A {
public:
	virtual void print() { cout << "class A\n"; }
};

class B : public A {
public:
	void print() { cout << "class B\n"; }
};

int main() {
	A a;
	B b;
	A* pa = &a;
	B* pb = &b;

	pa->print();
	pb->print();
	pb->A::print();
}
Каким образом в случае
Код:
 pa->print(); pb->print();
вызываются методы именно своих классов -- очевидно. Адреса этих методов есть в соответствующих этим классам таблицах vtbl.

Но откуда указателю pb удается вызвать
Код:
 pb->A::print()
? Ведь адреса этой функции нет в его виртуальной таблице (как я полагаю). Кто знает?

Последний раз редактировалось I_I_I; 30.07.2013 в 08:46.
I_I_I вне форума Ответить с цитированием
Старый 30.07.2013, 08:30   #2
ROD
Linux C++ Qt ARM
Старожил
 
Аватар для ROD
 
Регистрация: 30.11.2008
Сообщений: 3,030
По умолчанию

<убрал ошибочные данные>

A:rint() черт... хочу тег для принудительного игнорирования смайликов внутри него не может быть вызван в принцыпе, поскольку этой функции не существует. Кроме того, через Classname::FunctionName() можно вызвать только статические функции.

типа такой:

Код:
class C
{
public:
   static void print(){std::cout<<"Class C"<<std::endl;}
}
Дилетант широкого профиля.

"Слова ничего не стоят - покажите мне код!" © Линус Торвальдс

Последний раз редактировалось ROD; 30.07.2013 в 08:52.
ROD вне форума Ответить с цитированием
Старый 30.07.2013, 08:44   #3
Luuzuk
Форумчанин
 
Аватар для Luuzuk
 
Регистрация: 18.01.2012
Сообщений: 975
По умолчанию

Цитата:
Виртуальная функция на то и виртуальная, что она не имеет реализации (в данном классе). Странно, что компилятор не ругался.
А вы виртуальную с абстрактной не спутали, не?

Цитата:
Но откуда указателю pb удается вызвать
Выдержка из википедии:
Цитата:
Для каждого класса, имеющего хотя бы один виртуальный метод, создаётся таблица виртуальных методов. Каждый объект хранит указатель на таблицу своего класса. Для вызова виртуального метода используется такой механизм: из объекта берётся указатель на соответствующую таблицу виртуальных методов, а из неё, по фиксированному смещению, — указатель на реализацию метода, используемого для данного класса.
.............
для определения реализации виртуальной функции используется информация о типе объекта и вызывается «правильная» реализация, независимо от типа указателя
Благодарить в репутацию. Проклинать — туда же

Последний раз редактировалось Luuzuk; 30.07.2013 в 08:47.
Luuzuk вне форума Ответить с цитированием
Старый 30.07.2013, 08:50   #4
ROD
Linux C++ Qt ARM
Старожил
 
Аватар для ROD
 
Регистрация: 30.11.2008
Сообщений: 3,030
По умолчанию

Цитата:
А вы виртуальную с абстрактной не спутали, не?
Ща глянул стандарт, да, немного ошибся. Ввела в заблуждение моя любимая конструкция virtual void functionname() = 0;
Дилетант широкого профиля.

"Слова ничего не стоят - покажите мне код!" © Линус Торвальдс
ROD вне форума Ответить с цитированием
Старый 30.07.2013, 10:21   #5
Igor95
Форумчанин
 
Регистрация: 03.01.2013
Сообщений: 388
По умолчанию

Потому, что производный класс "работает как" базовый. Отсюда, Вы,через указатель на производный класс вызываете виртуальный метод print() из области видимости класса A.

Последний раз редактировалось Igor95; 30.07.2013 в 10:56.
Igor95 вне форума Ответить с цитированием
Старый 30.07.2013, 10:28   #6
Igor95
Форумчанин
 
Регистрация: 03.01.2013
Сообщений: 388
По умолчанию

В данном случае получим две таблицы виртуальных функций:
A
0 A:rint()

и
B
0 B:rint()

Последний раз редактировалось Igor95; 30.07.2013 в 10:36.
Igor95 вне форума Ответить с цитированием
Старый 30.07.2013, 10:36   #7
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,493
По умолчанию

pb->A:rint() - это вообще не виртуальный вызов, адрес определяется на этапе компиляции.
waleri вне форума Ответить с цитированием
Старый 30.07.2013, 10:38   #8
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,493
По умолчанию

Цитата:
Сообщение от ROD Посмотреть сообщение
Кроме того, через Classname::FunctionName() можно вызвать только статические функции.
Не путайте Classname::FunctionName() с instance.Classname::FunctionName() или pointer->Classname::FunctionName()
waleri вне форума Ответить с цитированием
Старый 30.07.2013, 10:43   #9
Igor95
Форумчанин
 
Регистрация: 03.01.2013
Сообщений: 388
По умолчанию

Цитата:
Сообщение от waleri Посмотреть сообщение
pb->A:rint() - это вообще не виртуальный вызов, адрес определяется на этапе компиляции.
***Удалил. Написал я бред*****
Igor95 вне форума Ответить с цитированием
Старый 30.07.2013, 10:54   #10
Igor95
Форумчанин
 
Регистрация: 03.01.2013
Сообщений: 388
По умолчанию

Код:
#include <iostream>
class Base
{
public:
	virtual void print()
	{
		std::cout << "Base print() called" << std::endl;
	}
};

class Inherited: public Base
{
public:
	virtual void print()
	{
		std::cout << "Inherited print() called" << std::endl;
	}
};

void main()
{
	Base b;
	Inherited inh;
	Base *pB = &b;
	Base *pInh = &inh;
	pInh->Base::print(); // все ок
        pB->Inherited::print(); // ошибка! не member класса Base.
	system("pause");
}
Т.е, то, что я написал в своем первом посте: "работает как". Base не знает о существовании Inherited.
Igor95 вне форума Ответить с цитированием
Ответ


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

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Вопрос по функциям miragex Общие вопросы C/C++ 5 06.01.2013 00:13
C++ Вопрос по виртуальным методам Selestis Помощь студентам 5 09.09.2011 18:18
вопрос по функциям . Goratics Общие вопросы C/C++ 5 17.07.2011 12:42
Вопрос по функциям Antowka Паскаль, Turbo Pascal, PascalABC.NET 6 08.12.2008 22:45
глупый вопрос по функциям steck Общие вопросы Delphi 2 17.06.2007 15:40