с ++ передавая себя тайной себе - PullRequest
0 голосов
/ 05 января 2012

не могли бы вы помочь мне. Я передаю себя чисто виртуальной функции самого себя.

n->dataCallback(handler, n, hangup);

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

так что теперь в объявлении:

void MyClass::dataCallback(int handler, void *cbData, bool hangup) {
    MyClass *This = (MyClass*) cbData;
 ....
}

Теперь, когда я сравниваю Это (переменная выше) с этим (указатель объекта) во время выполнения, я получаю:

  1. Значения указателей (адресов объекта) различны.
  2. При проверке memeber varaible (This-> member) я нахожу в них разные значения. (Правильное значение в этом, тогда как Это содержит неопределенное (для меня случайное) значение. Обратите внимание, что на стороне вызывающего абонента значение, конечно, правильное, поэтому оно кажется волшебным образом изменяется во время самого вызова, и другого кода нет). между.

Как, черт возьми, это возможно? Любая идея?

Я провел 2 часа, размышляя над этим, также спросил других программистов безрезультатно.

Ответы [ 3 ]

2 голосов
/ 05 января 2012

Если у вас множественное наследование, приведение указателя к каждому из родительских классов может изменить адрес указателя. Учтите следующее:

class A
{
public:
    int a;
};

class B
{
public:
    int b;
};

class C : public A, B
{
};

Внутренний макет класса C будет содержать два целых числа a и b. Если вы наведите указатель с C* на A*, все будет хорошо. Если вы приведете его к B*, указатель необходимо будет отрегулировать, поскольку первый элемент в B должен быть целым числом b!

Если вы выполняете приведение, когда оба типа известны компилятору, он выполнит настройку так, как вам не видно - он просто работает. Компилятор знает, какой должна быть правильная настройка. Когда вы разыгрываете void*, этот механизм выходит из строя.

0 голосов
/ 05 января 2012

Это может произойти, если n является указателем на класс, производный от класса, реализующего dataCallback, и этот класс имеет несколько базовых классов. Только один (не пустой) базовый объект может иметь тот же адрес, что и полный объект. Вот пример, который иллюстрирует проблему:

#include <iostream>

struct Base {
    int stuff;
    virtual void f(void * p) {
        std::cout << (p == this ? "GOOD\n" : "BAD\n");
    }
};

struct Other {
    int stuff; 
    virtual void g() {}
};

struct Derived : Other, Base {};

int main()
{
    Derived t;
    t.f(&t);     // BAD: Passing pointer to Derived to member of Base
                 // (but not guaranteed to print "BAD" - layout is not specified)

    Base & b = t;
    b.f(&b);     // GOOD: Passing pointer to Base to member of Base
}
0 голосов
/ 05 января 2012

У нас нет полного тестового примера для работы, но если MyClass полиморфен и существуют связанные классы, то приведение может изменить значение указателя.Использование void* может нарушить это.

...