Гуры C++! Подскажите. (И не гуры тоже ;).)

Модератор: Модераторы разделов

sdk
Бывший модератор
Сообщения: 210

Гуры C++! Подскажите.

Сообщение sdk »

Привет, народ!

Если вам охота попудрить мозги С++-ом, читайте дальше ;).

А подскажите мне кто-нибудь более "гурнутый", чем я, как работает следующая ситуация.

Допустим у меня есть два класса. Пусть один из них будет Одиночкой (можно и глобальным для простоты, но это уже не модно ;) ). Так. Лучше я кодом опишу.

Код: Выделить всё

class Singleton
{
   Client *m_client; // см. ниже
public:
    static Singleton* self(); // Одиночка же;)
    void changeClient()
    {
            delete m_client; m_client=0;
            // ...... возможно действия по созданию нового Client-а
     }

};

И есть класс:

class Client
{
public:
     void someFunction()
     {
            Singleton::self()->changeClient();
      }
};


Как это отработает? То есть, что будет, если я из одного класса (Client) вызову метод другого (Singleton::changeClient()), который удалит объект первого класса (Client)?
Только что написал тестовую программку - все работает. В смысле не слетает. И даже если я после вызова changeClient() в someFunction() поставлю cout<<this, работает.
Работает-то работает, но что по этому поводу говорит стандарт?
В частности, интересуют две ситуации:
а) После вызова changeClient() в someFunction() следуют еще какие-то действия
б) Вызов changeClient() - последний в someFunction();
Возможно, а) рискованно, но как насчет б)?

Нормально так делать или лучше забабацать какой-нибудь сборщик ненужных объектов?

А может я переработал и все это очевидно ;). Если я вам запудрил мозги - ничего не знаю, я вначале предупреждал :D.
Серьезность - это способ сделать простые вещи сложными.
Если много знать - устанут глаза. Если много спать - то нет.
Нас никому не сбить с пути - нам пофигу куда идти.
:-)
Спасибо сказали:
Аватара пользователя
elide
Бывший модератор
Сообщения: 2421
Статус: Übermensch
ОС: лялих

Re: Гуры C++! Подскажите.

Сообщение elide »

так я не понял, а в чем проблема?
cout<<this - это экстрим. работает только потому, что после удаления объекта выделенная память отдается не сразу. вообще-то это чистый SIGSEGV. при условии, конечно, что changeClient убивает именно тот объект Client, для которого эту самую changeClient и вызывают. что из приведенного кода совсем не очевидно....

а вообще, поиграйся лучше с delete this; (:
слава роботам!
Спасибо сказали:
sdk
Бывший модератор
Сообщения: 210

Re: Гуры C++! Подскажите.

Сообщение sdk »

Да, elide, ты прав, не очевидно :). Но ты догадался правильно - я именно это имел ввиду: вызывает тот Client, которого delet-ит Singleton.

То есть это все SIGSEGV, да?
Ну, это на самом деле не очень неожиданно....
Но... Если changeClient() - последний вызов в someFunction(), что тогда? Ведь там дальше ничего нету - удалиться себе спокойно и все.
Хотя... Может до закрывающей фигурной скобочки воспоследуют какие-нибудь скрытые вызовы скрытых функций через this... Которого уже нет... Так?

Чую, что все это - зело очевидно, но чего-то в голове запуталось :). Знаешь, бывает такое... :D
Серьезность - это способ сделать простые вещи сложными.
Если много знать - устанут глаза. Если много спать - то нет.
Нас никому не сбить с пути - нам пофигу куда идти.
:-)
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: Гуры C++! Подскажите.

Сообщение Zeus »

Я тоже никакой проблемы не вижу.
Никакого доступа к данным не описано: Singleton не имеет указателя на конкретный экземпляр Client'а из которого вызвана функция changeClient().
Соответственно что он там удаляет в строке "delete m_client;" - это его личные проблемы.

Сдаётся мне sdk имел ввиду какую-то более конкретную задачу, чем описал в коде.
Спасибо сказали:
sdk
Бывший модератор
Сообщения: 210

Re: Гуры C++! Подскажите.

Сообщение sdk »

Нет, Zeus я как раз и имею в виду конкретный указатель на Client :).
То есть у меня схема такая:
1. Singleton где-то создает объект класса Client и помещает указатель на него в m_client.
2. В какой-то момент времени этот самый объект класса Client вызывает Singleton::changeClient() (из someFunction(), например)
3. Singleton::changeClient() удаляет объект вызвавший эту функцию. В этом фишка.
4. ??? Управление возвращается в someFunction() и... ?
Что дальше? Управление возвращается в контекст уже несуществующего объекта.
Понятно, что если бы там были операции с данными, была бы бяка.
Но вот вопрос, что если там ничего нету кроме закрывающей фигурной скобки? :)
И следом еще вопрос: есть ли там какие-нибудь скрытые (читай вставленные компилятором и невидимые программисту) вызовы?
Ну там обращения к vtable или еще чего в этом духе.

Может я просто непонянто излагаю? :D
Серьезность - это способ сделать простые вещи сложными.
Если много знать - устанут глаза. Если много спать - то нет.
Нас никому не сбить с пути - нам пофигу куда идти.
:-)
Спасибо сказали:
Аватара пользователя
elide
Бывший модератор
Сообщения: 2421
Статус: Übermensch
ОС: лялих

Re: Гуры C++! Подскажите.

Сообщение elide »

ну если у тебя нет виртуального полиморфизма, то у этого объекта может вообще не быть vtbl. так что не заморачивайся...
вообще, если нет обращения к данным, то проблем никаких не возникает.
причем, даже если this == NULL; то все равно можно делать this->someOtherFunc(); например.
вообще, это же известный фишк: ((SomeClass*)NULL)->someMethod(); (:
слава роботам!
Спасибо сказали:
sdk
Бывший модератор
Сообщения: 210

Re: Гуры C++! Подскажите.

Сообщение sdk »

Ух ты! А я не знал! Серьезно что ли? :) А что будет? Ничего. Как, например, при delete 0?
Серьезность - это способ сделать простые вещи сложными.
Если много знать - устанут глаза. Если много спать - то нет.
Нас никому не сбить с пути - нам пофигу куда идти.
:-)
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: Гуры C++! Подскажите.

Сообщение Zeus »

sdk писал(а):
21.02.2006 00:00
1. Singleton где-то создает объект класса Client и помещает указатель на него в m_client.

Ну допустим...

2. В какой-то момент времени этот самый объект класса Client вызывает Singleton::changeClient() (из someFunction(), например)

Ну во-первых, по коду не видно, что объект Client "знает" о конкретном объекте Singleton, которому он принадлежит.
Во-вторых, он вызывает changeClient из указателя, который ему вернула СТАТИЧЕСКАЯ функция!
Она выполняется ВНЕ контекста объекта и не может иметь доступ к его внутренним данным (в т.ч. и указателю Client* m_client).
Я вообще её воспринял как фабрику Singleton'ов, тогда получается в строке
Singleton::self()->changeClient() СОЗДАЁТСЯ (хотя в коде нигде этого и не видно, но по другому быть не может - ты же отказался от глобальных объектов) новый объект Singleton и у него вызывается ф-я changeClient, удаляющая невесть что (кстати, вполне повод для sigfault'а).
Короче, приведённый псевдокод слишком схематичен - настолько, что, как видишь, допускает разные толкования.
Спасибо сказали:
sdk
Бывший модератор
Сообщения: 210

Re: Гуры C++! Подскажите.

Сообщение sdk »

Zeus, там все правильно :). Сейчас расскажу.
Я вначале оговорился, что буду вести речь об Одиночке, подразумевая, что читающие о нем знают ;).
Это паттерн такой, который гарантирует, что не может быть создано более одного объекта определенного класса. Статическая функция self() - это часть интерфейса Одиночки, которая всегда возвращает ОДИН И ТОТ ЖЕ объект класса Singleton, а как и когда он создается пользователей класса не колышит, это скрыто внутри реализации Singleton. Обычно создается при первом вызове self().

Теперь основываясь на этом комментирую твое сообщение.
Ну во-первых, по коду не видно, что объект Client "знает" о конкретном объекте Singleton, которому он принадлежит.

Client "знает" о конкретном объекте Singleton, потому что этот объект всего один. Всегда.
Во-вторых, он вызывает changeClient из указателя, который ему вернула СТАТИЧЕСКАЯ функция!
Она выполняется ВНЕ контекста объекта и не может иметь доступ к его внутренним данным (в т.ч. и указателю Client* m_client).

Правильно, она (self) не может. Но она возвращает указатель объект класса Singleton, который может. И хочет :). И имеет. Доступ к своим членам :).

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

Да, может я и слишком общо (вот дурацкое слово!) обрисовал. Ну да ладно, вроде бы уже разобрались. Спасибо тебе!

Happy coding! ;)
Серьезность - это способ сделать простые вещи сложными.
Если много знать - устанут глаза. Если много спать - то нет.
Нас никому не сбить с пути - нам пофигу куда идти.
:-)
Спасибо сказали:
Аватара пользователя
agbr
Сообщения: 486
ОС: openSUSE 10.2

Re: Гуры C++! Подскажите.

Сообщение agbr »

большой барабум!
jabber: agbr@jabber.ru

против проприетарного ПО в GNU/Linux
Спасибо сказали:
sdk
Бывший модератор
Сообщения: 210

Re: Гуры C++! Подскажите.

Сообщение sdk »

Спасибо, уважаемый agbr!!!
Это именно тот ответ, который мне был нужен.
А то слишком умно получилось :D.

Барабумище!!! :)
Серьезность - это способ сделать простые вещи сложными.
Если много знать - устанут глаза. Если много спать - то нет.
Нас никому не сбить с пути - нам пофигу куда идти.
:-)
Спасибо сказали: