почему результат не в моих ожиданиях? - PullRequest
0 голосов
/ 26 сентября 2011
#include <iostream>
using namespace std;
typedef void (*pFun)(void);
class A
{
private:    
    int a; 
    int b;
    virtual void outPrint()
    {
        cout << b << endl;
    }
 public:
    A()
    {
        a = 3;      
        b = 4;
    }
};

int main() 
{   
    A obj;
    cout << *((int*)(&obj)+1) << endl;
    pFun pFunc;     
    pFunc = (pFun)*((int*)*(int*)(&obj));   
    pFunc();
    system("pause");
    return 0; 
}

когда я вызываю pFunc (), я думаю, что результат должен быть 4, но на самом деле это случайное число.и я отлаживаю программу, обнаружив, что pFunc указывает на функцию outPrint.я не знаю почему, плз, помогите мне

Ответы [ 4 ]

2 голосов
/ 26 сентября 2011

Похоже, вы предполагаете, что адрес объекта obj можно интерпретировать как адрес функции определенного вами типа.

Не может.

Я не совсем уверен, почему у вас такое предположение для начала. Вы, вероятно, предполагаете что-то о внутренней реализации динамической отправки. Но обратите внимание: A::outPrint, который вы ожидаете вызвать, принимает 1 параметр (this, который явно не определен), тогда как ваш typedef не предполагает никаких параметров. Таким образом, даже если приведение адресов работает нормально, а адрес, который вы получаете, является адресом функции-члена (с самого начала это натяжение), ваш вызов неверен.

Если вы измените typedef на:

typedef void (*pFun)(A*);

и звонок на

pFunc(&obj);

Это может сработать. Тем не менее, насколько мне известно, поведение по спецификации не определено.

1 голос
/ 26 сентября 2011

Добавление 1 к int* имеет определенное поведение только в случае обхода int[].

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

Попробуйте решить проблему таким образом, чтобы использовать не детали компилятора, а стандарт.

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

0 голосов
/ 26 сентября 2011

Вы полагаетесь на различное «неопределенное поведение», следовательно, результат зависит от того, на каком компиляторе и платформе вы работаете.

(int *) & obj + 1 (лучше, если вы напишите ((int *)& obj) +1, чтобы избежать неправильной интерпретации) не обязательно является b членом.Между членами может быть заполнение, и & obj может не совпадать с &(obj.a), являющимся полиморфным объектом obj (поэтому может иметь указатель vtable поверх него).

Если это так,*(int*)&obj - это адрес vtable, который рассматривается как int.Преобразуя его в int* (при условии, что int и указатель имеют одинаковые размеры), он указывает на первую запись vtable (скорее всего, адрес outPrint), отсюда и «случайное число».

0 голосов
/ 26 сентября 2011

Я не совсем уверен, что именно вы пытаетесь сделать. Похоже, вы пытаетесь напрямую манипулировать указателем, чтобы получить адрес метода, но это очень плохая идея по 6 различным причинам. Можно получить указатель на метод класса, но он не привязан к объекту, поэтому вам нужно быть осторожным.

Я бы предположил, что у вас есть фундаментальное неправильное понимание указателей и классов C ++, которые необходимо исправить, прежде чем вы сможете безопасно справиться с любым из них. Большинству людей не нужны указатели на функции, и почти никто не нуждается в указателях методов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...