У меня странная проблема с указателем this в деструкторе базового класса.
Описание проблемы:
У меня есть 3 класса: A1 , A2 , A3
A2 наследуется публично от A1 и наследуется от A3
class A2:private A3, public A1 {...}
A3 имеет функцию getPrimaryInstance () ..., которая возвращает ссылку типа A1 на
A2 экземпляр:
A1& A3::getPrimaryInstance()const{
static A2 primary;
return primary;
}
И конструктор A3 выглядит следующим образом:
A3(){
getPrimaryInstance().regInst(this);
}
(где regInst (...) - это функция, определенная в A1 , которая сохраняет указатели на все A3 экземпляры)
Аналогично деструктор A3 :
~A3(){
getPrimaryInstance().unregInst(this);
}
^ Вот где возникает проблема!
Когда статический A2 -экземпляр с именем primary разрушается при завершении программы, вызывается деструктор A3 , но внутри ~ A3 Я пытаюсь получить доступ к функции в том же экземпляре, который уничтожаю.
=> Нарушение прав доступа во время выполнения!
Поэтому я подумал, что это можно исправить с помощью простого оператора if, например:
~A3(){
if(this != (A3*)(A2*)&getPrimaryInstance()) //Original verison
//if (this != dynamic_cast<A3*>(static_cast<A2*>(&getPrimaryInstance())))
//Not working. Problem with seeing definitions, see comments below this post
getPrimaryInstance().unregInst(this);
}
(Причиной двойного приведения является наследство:)
A1 A3
, \ /
, A2
(Но это не важно, могло бы быть просто (int) или как-то еще)
Кикер в том, что он все еще падает.
Выполнение кода с помощью отладчика показывает, что когда мой A2 primary -instance получает уничтожает указатель this в деструкторе и адрес, который я получаю при вызове getPrimaryInstance () по какой-то причине не совпадает вообще! Я не могу понять, почему адрес, на который указывает этот , всегда отличается от того, каким он должен быть (насколько мне известно). (
Делаем это в деструкторе:
int test = (int)this - (int)&getPrimaryInstance();
Также показал мне, что разница не постоянна (у меня была краткая теория, что существует некоторое постоянное смещение), так что это как два совершенно разных объекта, когда они должны быть одинаковыми. (
Я пишу в VC ++ Express (2008).
И, немного погуглив, нашел следующую статью MS:
ИСПРАВЛЕНИЕ: Указатель «this» неверен в деструкторе базового класса
Это не та же проблема, что и у меня (и она также была якобы исправлена в C ++. Net 2003). Но несмотря на то, что симптомы казались одинаковыми и , они представляли собой простой обходной путь, поэтому я решил попробовать:
Удалил неработающее - if -статейство и добавил в virtual перед вторым наследованием к A2 , например так:
class A2:private A3, public A1 {...} // <-- old version
class A2:private A3, virtual public A1 {...} //new, with virtual!
И ЭТО РАБОТАЛО! Указатель this по-прежнему неверен, но больше не дает нарушения доступа.
Итак, мой главный вопрос: почему?
Почему этот -пункт не указывает на то, где он должен (?)?
Почему добавление virtual к наследованию, как описано выше, решает его (несмотря на то, что this по-прежнему указывает куда-то еще, чем & getPrimaryInstance () )?
Это ошибка? Может кто-нибудь попробовать это в среде без MS?
И самое главное: Это безопасно ?? Конечно, он больше не жалуется, но я все еще волнуюсь, что он не делает то, что должен. : S
Если кто-то знает об этом или имеет опыт и может помочь мне понять это, я был бы очень благодарен, так как я все еще изучаю C ++, и это совершенно за пределами моих текущих знаний.