Re[15]: Вызов виртуального метода для класса
От: elcste  
Дата: 23.10.04 03:58
Оценка: :)
Здравствуйте, erithion aka tyomik, Вы писали:

E>>c::fn — виртуальная функция.


EAT>Еще раз повторюсь, меня не интересуют стандарты, несмотря на то, что я тоже читал Страуструпа и другую не менее интересную литературу и тоже прекрасно помню, что всеми ими такой метод класса обзывается виртуальным.


То есть эту функцию невиртуальной называете только Вы. Или еще кто-то?

EAT>С точки же зрения исследователя, я знаю другое, а именно, что это чистый метод класса в реализации МС С++ компилятора.


Вот только меня, в свою очередь, совершенно не интересует "реализация МС С++ компилятора". В данный момент я работаю с процессором Blackfin (ADSP-BF561), и мне интересен код, который генерирует VisualDSP++ от Analog Devices. Не хотите исследовать его для разнообразия?

    .file ".\test.cpp";

    .section program;

.epctext:

    .align 2;
_fn__1aFv:
// ".\test.cpp" line 12 col 18
        link  12;
// ".\test.cpp" line 14 col 9
//         -- 3 bubbles --
        R0.L = .epcrodata+16;
        R0.H = .epcrodata+16;
        CALL.X _printf;
        P0=[FP+ 4];
        unlink;
//         -- 3 bubbles --
        JUMP (P0);

._fn__1aFv.end:
    .type _fn__1aFv,STT_FUNC;

    .align 2;
_main:
// ".\test.cpp" line 31 col 5
        [--SP]=RETS;
        [--SP]=FP;
        FP = SP ;
        [--SP]=(P5:4);
//         -- 3 bubbles --
        SP +=  -12;
        CALL.X ___mark_dtor;
// ".\test.cpp" line 33 col 8
        R0 =   12;
        CALL.X ___nw__FUl;
        P5 = R0 ;
        CC =  R0 ==  0;
        P4 =   0;
        IF CC JUMP  ._P2L2 ;
// ".\test.cpp" line 10 col 9
        R0.L = .epcrodata;
        R0.H = .epcrodata;
// ".\test.cpp" line 33 col 8
        P4 = P5 ;
        R1.L = ___vtbl__1a;
        R1.H = ___vtbl__1a;
        P4 +=  8;
        [P5+ 4] = P4;
        [P5+ 8] = R1;
// ".\test.cpp" line 10 col 9
        CALL.X _printf;
        R0.L = ___vtbl__1c;
        R0.H = ___vtbl__1c;
        P0.L = .epcdata;
        P0.H = .epcdata;
        [P5+ 0] = R0;
        P0=[P0+ 4];
// ".\test.cpp" line 23 col 9
        R0.L = .epcrodata+24;
        R0.H = .epcrodata+24;
// ".\test.cpp" line 10 col 9
//         -- 2 bubbles --
        [P4+ 0] = P0;
// ".\test.cpp" line 23 col 9
        CALL.X _printf;
        P4 = P5 ;

._P2L2:
// ".\test.cpp" line 34 col 5
        P1=[P4+ 0];
//         -- 4 bubbles --
        R0=W[P1+ 8] (X);
        P0 = R0 ;
        P1=[P1+ 12];
//         -- 3 bubbles --
        P0 = P4 + P0;
        R0 = P0 ;
        CALL (P1);
// ".\test.cpp" line 35 col 5
        R0 = P4 ;
        CALL.X ___dl__FPv;
        SP +=  12;
        (P5:4)=[SP++];
// ".\test.cpp" line 36 col 5
//         -- 3 bubbles --
        R0 =   0;
        P2=[SP+ 4];
        FP=[SP+ 0];
        SP +=  8;
//         -- 2 bubbles --
        JUMP (P2);

._main.end:
    .global _main;
    .type _main,STT_FUNC;

    .align 2;
_fn__1cFv:
// ".\test.cpp" line 25 col 10
        link  12;
// ".\test.cpp" line 27 col 9
//         -- 3 bubbles --
        R0.L = .epcrodata+40;
        R0.H = .epcrodata+40;
        CALL.X _printf;
        P0=[FP+ 4];
        unlink;
//         -- 3 bubbles --
        JUMP (P0);

._fn__1cFv.end:
    .type _fn__1cFv,STT_FUNC;

.epctext.end:

    .extern _printf;
    .type _printf,STT_FUNC;
    .extern ___mark_dtor;
    .type ___mark_dtor,STT_FUNC;
    .extern ___nw__FUl;
    .type ___nw__FUl,STT_FUNC;
    .extern ___dl__FPv;
    .type ___dl__FPv,STT_FUNC;

    .section data1;

    .align 8;
.epcdata:
    .type .epcdata,STT_OBJECT;
.epc.cplus.compiled:
    .type .epc.cplus.compiled,STT_OBJECT;
    .byte = 0x00,0x00,0x00,0x00;
    .byte4 = ___vtbl__1a__1c;
.epcdata.end:

    .section constdata;

    .align 8;
.epcrodata:
    .type .epcrodata,STT_OBJECT;
    .byte = 0x61,0x3A,0x3A,0x63,0x6F,0x6E,0x73,0x74,0x72,0x75,0x63,0x74;
    .byte = 0x6F,0x72,0x00,0x00,0x61,0x3A,0x3A,0x66,0x6E,0x00,0x00,0x00;
    .byte = 0x63,0x3A,0x3A,0x63,0x6F,0x6E,0x73,0x74,0x72,0x75,0x63,0x74;
    .byte = 0x6F,0x72,0x00,0x00,0x63,0x3A,0x3A,0x66,0x6E,0x00;
.epcrodata.end:
    .align 4;
___vtbl__1a:
    .type ___vtbl__1a,STT_OBJECT;
    .byte = 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00;
    .byte4 = _fn__1aFv;
.___vtbl__1a.end:
    .align 4;
___vtbl__1c:
    .type ___vtbl__1c,STT_OBJECT;
    .byte = 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00;
    .byte4 = _fn__1cFv;
.___vtbl__1c.end:
    .align 4;
___vtbl__1a__1c:
    .type ___vtbl__1a__1c,STT_OBJECT;
    .byte = 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xFF,0x00,0x00;
    .byte4 = _fn__1cFv;
.___vtbl__1a__1c.end:

    .section data1;

Обратите внимание на то, что вызов виртуальной функции c::fn происходит косвенно, через таблицу виртуальных функций, несмотря на совпадение в данном случае статического и динамического типов указуемого i объекта.

EAT>Его виртуальность возникает вследствие перекрытия имен, которая разрешается в пользу виртуальности метода наследника.


Bravo! You made my day!

E>>Виртуальные базовые классы инициализируются только из конструктора most derived class.

EAT>Я сказал про параметр, вследствие равенства нулю которого вызова конструктора базового класса вообще не происходит.

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

#include <iomanip>
#include <iostream>

struct foo
{
    bool qux;
    foo() : qux(true) {}
    foo(bool qux) : qux(qux) {}
};

struct bar : virtual foo
{
    bar() : foo(false) {}
};

struct baz : bar {};

int main()
{
    if(baz().qux)
        std::cout << "Surprise!" << std::endl;
}

E>>P.S. Учите язык.
EAT>Спасибо! Торжественно обещаю
EAT>А какой? Алгол?

Нет, русский.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.