Я изучаю C ++, используя «мышление в C ++» Экеля. В нем говорится следующее:
- Если класс содержит виртуальные методы, для этого класса создается таблица виртуальных функций и т. Д. Работа таблицы функций поясняется примерно. (Я знаю, что vtable не является обязательным, но Visual C ++ создает его.)
- Вызывающий объект передается вызываемой функции в качестве аргумента. (Это может быть не так для Visual C ++ (или любого компилятора).) Я пытаюсь выяснить, как VC ++ передает вызывающий объект в функцию.
Чтобы проверить обе точки в Visual C ++, я создал следующий класс (с использованием Visual Studio 2010, WinXP Home 32bit):
ByteExaminer.h:
#pragma once
class ByteExaminer
{
public:
short b[2];
ByteExaminer(void);
virtual void f() const;
virtual void g() const;
void bruteFG();
};
ByteExaminer.cpp:
#include "StdAfx.h"
#include "ByteExaminer.h"
using namespace std;
ByteExaminer::ByteExaminer(void)
{
b[0] = 25;
b[1] = 26;
}
void ByteExaminer::f(void) const
{
cout << "virtual f(); b[0]: " << hex << b[0] << endl;
}
void ByteExaminer::g(void) const
{
cout << "virtual g(); b[1]: " << hex << b[1] << endl;
}
void ByteExaminer::bruteFG(void)
{
int *mem = reinterpret_cast<int*>(this);
void (*fg[])(ByteExaminer*) = { (void (*)(ByteExaminer*))(*((int *)*mem)), (void (*)(ByteExaminer*))(*((int *)(*mem + 4))) };
fg[0](this);
fg[1](this);
}
Навигация по vtable в bruteFG()
работает - когда я звоню fg[0](this)
, вызывается f()
. Однако, что НЕ работает, так это передача this
функции - это означает, что this->b[0]
печатается неправильно (вместо этого появляется мусор. Мне действительно повезло, что это не приводит к segfault).
То есть фактический результат для
ByteExaminer be;
be.bruteFG();
есть:
virtual f(); b[0]: 1307
virtual g(); b[1]: 0
Так как мне поступить, чтобы получить правильный результат? Как указатели this
передаются в функции в VC ++?
(Примечание: я не собираюсь так серьезно программировать, никогда. Это "для лулзов"; или для обучения. Поэтому не пытайтесь преобразовать меня в правильный язык С ++ :) )