2012-01-05 4 views
0

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

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

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

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

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

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

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

Как на земле это возможно? Любая идея?

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

+0

Вы используете множественное наследование? – sth

+2

Просмотрите мои изменения. Stack Overflow использует [markdown] (http://stackoverflow.com/editing-help), и вы должны по крайней мере познакомиться с основными частями, такими как отступы кода. – meagar

+0

Может ли [это] (http://stackoverflow.com/a/3725440/140719) или [что] (http://stackoverflow.com/a/3108745/140719) вам помочь? – sbi

ответ

2

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

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

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

+0

Привет LRO, Да, класс является полиморфным, он использует множественное наследование, чистый виртуальный dataCallback находится в одном из таких интерфейсов (базовый класс). Я думаю, что я не понимаю, как кастинг может изменить значение указателя, но если это возможно, вы, вероятно, ответили на мой вопрос. Было бы неплохо узнать немного больше о том, как сделать кастинг. Тем временем я изменяю void * на соответствующий интерфейс и вижу, исправляет ли он его ... Я вернусь ... – user1132655

+0

@ user1132655: Марк объяснил это довольно хорошо. –

0

Это может произойти, если 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

Привет всем, спасибо всем за ответ. Все ответы были правильными, я просто не могу отметить каждый :) Когда я изменил void * на правильный явный базовый класс, Ive получил правильное значение. Я все еще чувствую эту проблему немного сложной (я бы не догадался об этом сам), но я делаю домашнее задание :) – user1132655

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