vfptr
От: Fiend  
Дата: 10.09.02 10:58
Оценка:
Вижуал, как я понимаю, помещает указатель на табл. вирт. функций в начало объекта . То есть указатель на объект есть по сути указатель на указатель. Если я наследую нсколько классов, то независимо от того, в каком порядке я ставлю классы в списке наследования (может я это и неправильно назвал, но д.б. понятно) базовые классы с виртуальными функциями идут первыми, а неполиморфные классы пихаются в конец.
Но вот что-то у меня в гцц все не так. Сначала идут данные, а указатель где-то позади. ПОЧЕМУ ТАК?
Re: vfptr
От: dupamid Россия  
Дата: 10.09.02 11:09
Оценка:
Здравствуйте Fiend, Вы писали:

F>Но вот что-то у меня в гцц все не так. Сначала идут данные, а указатель где-то позади. ПОЧЕМУ ТАК?


Потому что реализация может ракладывать не POD класс почти как захочет, полагаться на это нельзя. А чем подход gcc (если я правильно понял) не устраивает?

Если надо чтобы указатель на таблицу виртуальных функций был вначале, то надо завести абстактный базовый класс, как делается в COM. Хотя даже в этом случае Стандарт ничего не гарантирует.
Re: vfptr
От: Андрей Тарасевич Беларусь  
Дата: 10.09.02 16:37
Оценка:
Здравствуйте Fiend, Вы писали:

F>Вижуал, как я понимаю, помещает указатель на табл. вирт. функций в начало объекта . То есть указатель на объект есть по сути указатель на указатель. Если я наследую нсколько классов, то независимо от того, в каком порядке я ставлю классы в списке наследования (может я это и неправильно назвал, но д.б. понятно) базовые классы с виртуальными функциями идут первыми, а неполиморфные классы пихаются в конец.


Нет. При множественном наследовании базовые классы располагаются внутри класса-наследника в том порядке, к котором они указаны в списке наследования. Потому при множественном наследовании в классе-наследнике кроме его собственного указателя на VMT (это действительно помещается в начало объекта) может сидеть еще несколько указателей на VMT (базовых классов). Эти дополнительные указатели на VMT могут быть раскиданы по классу-наследнику как угодно.

F>Но вот что-то у меня в гцц все не так. Сначала идут данные, а указатель где-то позади. ПОЧЕМУ ТАК?


Потому что так захотелось GCC. Куда поместить указатель на VMT в классе — личное дело компилятора.
Best regards,
Андрей Тарасевич
Re: vfptr
От: aLEXa123  
Дата: 10.09.02 19:51
Оценка:
Не помню где , но удалось найти такой пример — погляди в отладчике на адрес objDer
#include "stdafx.h"  //virtual1.cpp
#include <iostream>
using namespace std;

class Base1 {
  public:
  Base1(){ 
  }
    virtual void f() { cout << "Base1::f" << endl; }
    virtual void g() { cout << "Base1::g" << endl; }
};

class Base2 {
    virtual void f() { cout << "Base2::f" << endl; }
    virtual void g() { cout << "Base2::g" << endl; }
};

class Base3 {
  public:
    virtual void f() { cout << "Base3::f" << endl; }
    virtual void g() { cout << "Base3::g" << endl; }
};

class Derived : public Base1, public Base2, public Base3 {
  public:
  Derived() {
  }
    virtual void fd() { cout << "Derived::fd" << endl; }
    virtual void gd() { cout << "Derived::gd" << endl; }
};

typedef void(*Fun)(void);
#define SOME_VALUE 1
#define _ATL_PACKING 8
//macro returns the offset of the base class vptr in the drive 
#define offsetofclass(base, derived) \
((DWORD)(static_cast<base*>((derived*)_ATL_PACKING))-_ATL_PACKING)

int main() {
    Derived objDer;
    Fun pFun = NULL;
    // calling 1st virtual functions of Base1
    pFun = (Fun)*((int*)*(int*)((int*)&objDer+0)+0);
    pFun();
    pFun = (Fun)*(*(int**)((int*)&objDer+0)+1);
    pFun();
    // calling 1st virtual functions of Derived
    pFun = (Fun)*(*(int**)((int*)&objDer+0)+2);
    pFun();
    pFun = (Fun)*(*(int**)((int*)&objDer+0)+3);
    pFun();
    // calling 1st virtual functions of Base2
    pFun = (Fun)*(*(int**)((int*)&objDer+1)+0);
    pFun();
        pFun = (Fun)*(*(int**)((int*)&objDer+1) +1);    
    pFun();
    // calling 1st virtual functions of Base3
    pFun = (Fun)*(*(int**)((int*)&objDer+2)+0);
    pFun();
    //pFun = (Fun)*(*(int**)((int*)&objDer+2)+1);
    //pFun();
    cout << "increment address of objDer by 8 (assuming it`s a char*)" << endl;
    int **dblptr = (int **) ((char *)&objDer + offsetofclass(Base3, Derived) );
    void(*pFun2)() =  ( void(*)(void) )**dblptr;
    pFun2();
    void *pvoid = (char *)&objDer + offsetofclass(Base3, Derived);
    ((Base3*)(pvoid))->g();
    cout << (DWORD)static_cast<Base1*>((Derived*)SOME_VALUE)-SOME_VALUE << " ";
    cout << (DWORD)static_cast<Base2*>((Derived*)SOME_VALUE)-SOME_VALUE << " ";
    cout << (DWORD)static_cast<Base3*>((Derived*)SOME_VALUE)-SOME_VALUE << endl;
    cout << offsetofclass(Base1, Derived) << " ";  //0
    cout << offsetofclass(Base2, Derived) << " ";  //4
    cout << offsetofclass(Base3, Derived) << endl; //8    
    return 0;
}
Re[2]: vfptr
От: Fiend  
Дата: 11.09.02 07:11
Оценка:
Здравствуйте Андрей Тарасевич, Вы писали:

АТ>Здравствуйте Fiend, Вы писали:


F>>Вижуал, как я понимаю, помещает указатель на табл. вирт. функций в начало объекта . То есть указатель на объект есть по сути указатель на указатель. Если я наследую нсколько классов, то независимо от того, в каком порядке я ставлю классы в списке наследования (может я это и неправильно назвал, но д.б. понятно) базовые классы с виртуальными функциями идут первыми, а неполиморфные классы пихаются в конец.


АТ>Нет. При множественном наследовании базовые классы располагаются внутри класса-наследника в том порядке, к котором они указаны в списке наследования. Потому при множественном наследовании в классе-наследнике кроме его собственного указателя на VMT (это действительно помещается в начало объекта) может сидеть еще несколько указателей на VMT (базовых классов). Эти дополнительные указатели на VMT могут быть раскиданы по классу-наследнику как угодно.


Нет, тут я с Вами не согласен. Я проверял.

class A{public:
virtual void Nothing()const{}
  int k;
};
class B{public:
int n;
};
class C:public B, public A{};

int main(){
  C c;
  A * pa = &c;
  std::cout<<pa<<" "<<&c<<" "<<&c.n<<" "<<&c.k<<std::endl;
  return 0;
}


В вижуале у меня получается, что сначала идет А, а не B.

F>>Но вот что-то у меня в гцц все не так. Сначала идут данные, а указатель где-то позади. ПОЧЕМУ ТАК?


АТ>Потому что так захотелось GCC. Куда поместить указатель на VMT в классе — личное дело компилятора.


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