2015-06-10 6 views
0

Я читаю статью Бьярне: «Multiple Inheritance for C++».деталь компилятора этого указателя и виртуальных функций

В разделе 3 на стр. 370 Бьярне сказал, что «компилятор превращает вызов функции-члена в« обычный »вызов функции с« дополнительным »аргументом, этот« дополнительный »аргумент является указателем на объект для который вызывается функцией-членом. "

Рассмотрим простой класс A:

class A { 
    int a; 
    void f(int i); 
}; 

Вызов функции-члена A :: F:

A* pa; 
pa->f(2) 

преобразуется компилятором в "обычной функции вызова":

f__F1A(pa, 2) 

pa передается как указатель. Это легко понять для приведенного выше примера.

Рассмотрим следующий фрагмент кода:

class A {int a; void f(int);}; 
class B : A {int b; void g(int);}; 
class C : B {int c; void h(int);}; 

Вопрос 1:

Вызов функции-члена A :: F:

C* pc = new C; 
pc->g(int) 

преобразуется компилятором в «обычный вызов функции»:

g__G1C(pc, int) or g__G1B((*B)pc, int) 

Является ли этот указатель a * pc или (* B) pc? Другой вопрос: как компилятор знает, где функции-члены?

Приведем пример выше, добавив ключевое слово virtual.

class A { 
    int a; 
    virtual void f(int); 
    virtual void g(int); 
    virtual void h(int); 
}; 
class B : A {int b; void g(int); }; 
class C : B {int c; void h(int); }; 

Класса C объект С выглядит следующим образом:

С:

-----------    vtbl: 
+0: vptr --------------> ----------- 
+4: a      +0: A::f 
+8: b      +4: B::g 
+12: c      +8: C::h 
-----------    ----------- 

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

C* pc; 
pc->g(2) 

становится чем-то вроде:

(*((*pc)[1]))(pc, 2) 

бумага The Бьярне в Толе мне этот вывод.

Вопрос 2:

(1) В VTBL, я считаю, что эти указатели на функции назначены во время выполнения. Как компилятор знает, что второй указатель функции должен указывать на реализацию класса B g? Как его компилятор ?

(2) В приведенном выше примере все члены являются int и мы предполагаем, что компилятор присваивает 4-байтовой памяти для int. Что, если член равен char, компилятор по-прежнему назначает 4 байта памяти для символа? Или просто один байт?

(3) (*((*pc)[1]))(pc, 2), этот указатель здесь представляет собой компьютер, почему бы и нет (* B) pc? Есть ли какое-либо правило для передачи этого указателя?

Может ли кто-нибудь помочь мне ответить на эти вопросы? Я очень ценю это. Завтра у меня есть , который действительно относится к этим проблемам. Пожалуйста помоги!!!

+0

Кажется, что это заглянет в Clang/GCC, чтобы получить ответы. – VermillionAzure

+0

Не используйте форматирование цитаты для текста, который не цитируется, – EJP

ответ

1

Вопрос 1:

Вызов функции-члена A :: F:

C* pc = new C; 
pc->g(int) 

Это не вызов A :: F(). Это вызов B :: g().

преобразуется компилятором в "обычной функции вызова":

g__G1C(pc, int) or g__G1B((*B)pc, int) 

Является ли этот указатель а * ПК или (* B) ПК?

Ни то, ни другое. Это B*.

Другой вопрос: как компилятор знает, где находятся функции-члены?

Это не так. Он знает их имена. Компилятор назначает свои адреса.

Вопрос 2:

(1) Как знать, компилятор второго указатель функции должен указывать на реализацию класса В в части г? Как это делает компилятор?

Поскольку он является vtbl C, а C наследуется от B, а B имеет ближайшее определение g().

(2) В приведенном выше примере все члены являются int, и мы предполагаем, что компилятор назначает 4 байта памяти для int. Что, если элемент является char, компилятор все еще назначает 4 байта памяти для символа? Или просто один байт?

Это зависит от выравнивания и упаковки правил процессора, компилятор, опции компилятора, окружающих #pragmas и т.д.

(3) (* ((* шт) [1])) (pc, 2), этот указатель здесь является pc, почему бы не (* B) pc?

Это утверждение противоречит your other question. Это B*.

Есть ли какие-либо правила для пропуска этого указателя?

См. Выше.

+0

большое спасибо за ваш ответ. У меня есть еще один вопрос: http://stackoverflow.com/questions/30747633/compilers-detail-of-this-pointer Можете ли вы, пожалуйста, помочь мне взглянуть на него? – Fihop

+0

Для вопроса 2 указатели на функции указываются на соответствующие функции во время выполнения или на этапе компиляции? – Fihop

+0

@Fihop Это не важный вопрос. – EJP