2014-11-02 5 views
0

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

class protoCalc 
{ 
    private: 
     int x; 
     int y; 
     virtual int basicAddition() 
     { 
      return x + y; 
     } 
     virtual int basicMultiplication() 
     { 
      return x*y; 
     } 
public: 
    protoCalc(){ 
     x = 14; 
     y = 120; 
    } 
}; 

Доступ к x и y оказался достаточно простым; сделать так что я написал функцию (входит в мои мысли о том, как это работает, являются ли они правильно или нет):

int private_member_Print(void* proto) 
{ 
    protoCalc* medium = (protoCalc*)proto; 
    protoCalc halfway = *medium; 
    int* ptr = ((int *)(&halfway)); 
return ptr[1]; 

}

выше возвращает значение х, если PTR [ 2], он вернет значение y.

Теперь у меня есть два вопроса, первое из которых относится к ptr [0], указывающему на? Разве этот бит памяти не должен занимать частный член х, поскольку это первый член класса protoCalc? Если нет, то что занимает этот адрес?

Во-вторых, как мне получить доступ к виртуальным функциям? Моя первая интуиция заключалась в том, что адрес ptr [3] будет занимать виртуальная функция basicAddition() и ptr [4] функция basicMultiplication(), однако это не так. Когда это не удалось, моя следующая мысль заключалась в том, что ptr [0] содержал указатель на расположение виртуальной таблицы элементов, в которой были сохранены две функции, которые я искал. Однако это также оказалось ложным.

Как я могу получить доступ к этим виртуальным функциям вне класса, поскольку я получил доступ к частным членам x и y? Очевидно, что я мог бы изменить обстоятельства, чтобы облегчить их, но это победит цель проблемы.

+0

Это все неопределенное поведение. Предоставляйте публичные функции для доступа к частным членам, если это то, что вы хотите сделать. –

+2

Как только я вижу указатель на пустоту и листинг, я перестаю читать. Все, что следует, не будет хорошо для моего мозга. –

+0

Меньше ваших проблем, но ваши функции могут быть сделаны const. И если класс имеет виртуальные функции, он должен иметь виртуальный деструктор. –

ответ

0

Что вы сейчас делаете, это неопределенное поведение. В большинстве случаев компоновка объекта в памяти остается до компилятора, и вы не знаете, где компилятор помещает каждый член в память.

Это, как говорится, есть способ реализовать это, вы сильно злоупотребляете шаблонами. Я настоятельно рекомендую не делать этого и вместо этого предоставлять функции-члены для доступа к требуемым данным.

Вот пример этого в действии.

#include <iostream> 

class Priv { 
private: 
    int i; 
    void print() { 
     std::cout << i << std::endl; 
    } 

public: 
    Priv() : i(100) {} 

    void print_pub() { 
     std::cout << "Public" << std::endl; 
     this->print(); 
    } 
}; 

template<typename Tag> 
struct result { 
    /* export it ... */ 
    typedef typename Tag::type type; 
    static type ptr; 
}; 

template<typename Tag> 
typename result<Tag>::type result<Tag>::ptr; 

template<typename Tag, typename Tag::type p> 
struct rob : result<Tag> { 
    /* fill it ... */ 
    struct filler { 
    filler() { result<Tag>::ptr = p; } 
    }; 
    static filler filler_obj; 
}; 

template<typename Tag, typename Tag::type p> 
typename rob<Tag, p>::filler rob<Tag, p>::filler_obj; 

struct Priv_f { typedef void (Priv::*type)(); }; 
template class rob< Priv_f, &Priv::print >; 

struct Priv_i { typedef int Priv::*type; }; 
template class rob< Priv_i, &Priv::i >; 

int main() { 
    Priv p; 

    (p.*result<Priv_i>::ptr) = 1; 
    (p.*result<Priv_f>::ptr)(); 

} 

Объяснение шаблонных классов отнимают/результат можно найти here. Он должен работать через компиляторы.

+0

Я думаю, что вопрос более сфокусирован на реализации виртуальных функций. Вы пытаетесь осветить это, но не совсем правильно: это не реализация.Реализации не требуются для документирования того, как они реализуют виртуальные функции, и как они выставляют классы. Остальное может иметь отношение к тому, о чем спрашивает ОП, но не о том, что интересует OP. – hvd

+0

Фактически комментарий OP «Единственный код, который я могу изменить, находится в моей функции private_member_Print». совершенно явно отбрасывает этот подход. – hvd

+0

Да, я знаю, что есть намного более простые способы приблизиться к тому, что я пытаюсь выполнить, поэтому я упомянул об этом в основном вопросе: D. Я использую визуальную студию и через пробную версию, и ошибка обнаружила, что ptr [0] содержит указатель на vtable, однако проблема, с которой я сейчас сталкиваюсь, - это выяснить, как получить доступ к информации из таблицы vtable – LilLarryboy

Смежные вопросы