Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Сравнить два указателя 
V
    Опции темы
borisbn
Дата 9.10.2012, 08:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Здравствуйте.
Имеется два интерфейса
Код
class A {
public:
   virtual void fooA() = 0;
   virtual ~A() {}
};

class B {
public:
   virtual void fooB() = 0;
   virtual ~B() {}
};

и такой класс
Код
class MainSystem
{
public:
   void installA( A * a ) { m_a = a; }
   void installB( B * b ) { m_b = b; }

   MainSystem() : m_a( 0 ), m_b( 0 ) {}
   ~MainSystem() {
      if ( m_a == m_b ) { // <--- Не работает. Приведение к void* - тоже
         delete m_a;
      }
      else {
         delete m_a;
         delete m_b;
      }
   }
private:
   A * m_a;
   B * m_b;
};

Т.е. я хочу сделать следующее: если пользователь класса MainSystem наследовался от обоих интерфейсов и передал мне один и тот же указатель, то удалять его нужно один раз. Если он сделал два независимых наследника, то удалять нужно обоих.
Вопрос: как мне узнать какой вариант выбрал пользователь ?
P.S. Я пробовал наследовать оба интерфейса он некоего Base (пустого) и сравнивать не A* и B*, а Base* и Base*, но тоже безрезультатно.
Код
class Base {};
class A : public Base { ... };
class B : public Base { ... };
   ~MainSystem() {
      if ( (Base*)m_a == (Base*)m_b ) { // <--- Не работает.
...

http://liveworkspace.org/code/e9bc0e79aa98...1be0bfdb490cee3


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Alexeis
Дата 9.10.2012, 09:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 12
Всего: 459



Цитата(borisbn @  9.10.2012,  09:57 Найти цитируемый пост)
Т.е. я хочу сделать следующее: если пользователь класса MainSystem наследовался от обоих интерфейсов и передал мне один и тот же указатель, то удалять его нужно один раз. Если он сделал два независимых наследника, то удалять нужно обоих.

  Обычно делается подсчет ссылок. 2 раза присвоил, то счетчик ссылок +2. Вместо удаления уменьшаешь счетчик ссылок. Когда он станет равен нулю, то функция релиз удаляет объект сама.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
borisbn
Дата 9.10.2012, 09:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Для того, чтобы счётчик увеличился до 2-х нужно, чтобы этот счётчик был единым для обоих указателей (A* и B*). Если добавить счётчик в Base, то будут создано 2 счётчика... В общем, не пойму как реализовать подсчёт ссылок для данного случая.
http://liveworkspace.org/code/d06d40d33408...8bacf146f26a30b


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
baldina
Дата 9.10.2012, 10:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



delete 0 не вызывает неприятностей, поэтому удаляйте оба, только после удаления каждого присваивайте 0

Добавлено через 2 минуты и 49 секунд
но вообще-то тут где-то логическая неувязка, несоответствие RAII: кто владелец указателей?
наконец, можно умные указатели использовать

Это сообщение отредактировал(а) baldina - 9.10.2012, 10:03
PM MAIL   Вверх
mabrarov
Дата 9.10.2012, 10:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 100
Регистрация: 12.1.2011
Где: Казань

Репутация: 8
Всего: 9



Вообще, правильные варианты уже предложили.
Но если очень хочется, то можно через виртуальный базовый класс.
PM MAIL WWW Skype   Вверх
Alexeis
Дата 9.10.2012, 10:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 12
Всего: 459



Цитата(borisbn @  9.10.2012,  10:38 Найти цитируемый пост)
 Если добавить счётчик в Base, то будут создано 2 счётчика... В общем, не пойму как реализовать подсчёт ссылок для данного случая.

  А зачем реализовывать счетчик в интерфейсах? Реализуй его в конечном классе. Ты же написал в начале поста, что у тебя интерфейс. Интерфейс не предполагает использование полей данных внутри себя. Наследуй интерфейс от IUnknown и реализуй в конечном классе для обоих интерфейсов. 


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
borisbn
Дата 9.10.2012, 10:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



baldina, у меня же два указателя... соотв. присваивая 0 одному другой-то не поменяется...

mabrarov, спасибо! Именно то, что нужно.

Век живи, век учись...
/me пошёл читать про виртуальное наследование


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Alexeis
Дата 9.10.2012, 10:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 12
Всего: 459



Я для наследования 2х интерфейсов делал вот такой класс заготовочку. 
Код

template<typename tInterface1, typename tInterface2,
         typename tquery1 = tInterface1, typename tquery2 = tInterface2> 
class C2InterfacedObject : public tInterface1, public tInterface2
{
protected:
   volatile long  RefCount;

public:
    C2InterfacedObject( void ){RefCount = 0;};
    virtual ~C2InterfacedObject( void ){};

//IUnknown
    virtual ULONG   __stdcall AddRef( void ){return InterlockedIncrement(&RefCount);};
    virtual ULONG   __stdcall Release( void )
    {
        if (InterlockedDecrement(&RefCount) == 0)
        {
            delete this;
            return 0;
        }
        else
          return RefCount;
    }

    virtual HRESULT __stdcall QueryInterface(const _GUID &IID, void* *Obj)
    {
        if (Obj == NULL) return E_POINTER;

        if      (IsEqualGUID(__uuidof(tInterface1), IID) ||
            IsEqualGUID(__uuidof(tquery1),     IID))
            *Obj = static_cast<tInterface1*>(this);

        else if (IsEqualGUID(__uuidof(tInterface2), IID) ||
            IsEqualGUID(__uuidof(tquery2),     IID) ||
            IsEqualGUID(__uuidof(IUnknown),    IID))
            *Obj = static_cast<tInterface2*>(this);
        else
            *Obj = NULL;

        if (*Obj) static_cast<IUnknown*>(*Obj)->AddRef();
        return (*Obj) ? S_OK : E_NOINTERFACE;
    }
};


Наследуюсь от него и имею общий счетчик ссылок.

Это сообщение отредактировал(а) Alexeis - 9.10.2012, 10:40


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
borisbn
Дата 9.10.2012, 11:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Alexeis, спасибо, понятно. Но мне не очень подходит, т.к. я хочу минимизировать требования к пользователям моего класса MainSystem. Т.е. хочешь наследоваться только от одного интерфейса - пожалуйста, хочешь от двух - без проблем... как-то так...


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Alexeis
Дата 9.10.2012, 12:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 12
Всего: 459



Цитата(borisbn @  9.10.2012,  12:36 Найти цитируемый пост)
 Т.е. хочешь наследоваться только от одного интерфейса - пожалуйста, хочешь от двух - без проблем... как-то так... 

  Так в чем вопрос? Это пример как делается один счетчик на 2 интерфейса. В общем-то в твоем случае QueryInterface не нужен, просто если наследоваться от IUnknown, то можно использовать умный указатель ComPtr<> . Кстати, в бусте есть умный указатель с внешним счетчиком ссылок, тогда можно совсем не связываться с комом boost::intrusive_ptr


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
baldina
Дата 9.10.2012, 14:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



Цитата(borisbn @  9.10.2012,  10:38 Найти цитируемый пост)
baldina, у меня же два указателя

 smile верно
PM MAIL   Вверх
maxim1000
Дата 9.10.2012, 18:48 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 17
Всего: 110



Код

dynamic_cast<void*>(a)==dynamic_cast<void*>(b)



--------------------
qqq
PM WWW   Вверх
borisbn
Дата 9.10.2012, 19:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Цитата(maxim1000 @  9.10.2012,  18:48 Найти цитируемый пост)
dynamic_cast<void*>(a)==dynamic_cast<void*>(b)

Цитата(borisbn @  9.10.2012,  10:38 Найти цитируемый пост)
Век живи, век учись...

хммммммм. 
сначала увидел это сообщение с мобильного и проверить не было возможности (привет boostcoder'у))) и думал ответить, что это - ерунда, но потом добрался до "большого" компа - проверил - работает.
интересно, а что делает dynamic_cast для void* ????

maxim1000, не подскажешь, ты до этого методом тыка дошёл или прочитал где ? Если второе - дай ссыль, плиз.
И ещё вопрос - это случайно в gcc так получается или это чётко по стандарту ?

Спасибо.

Добавлено через 2 минуты и 29 секунд
Кстати, первое, что я попробовал - это
Код
(void*)a == (void*)b

и оно не отработало. reinterpret_cast и static_cast - тоже. 


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Alexeis
Дата 9.10.2012, 20:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 12
Всего: 459



Цитата(borisbn @  9.10.2012,  20:42 Найти цитируемый пост)
И ещё вопрос - это случайно в gcc так получается или это чётко по стандарту ?

Спасибо.

Цитата(http://msdn.microsoft.com/en-us/library/cby9kycs.aspx)

If type-id is void*, a run-time check is made to determine the actual type of expression. The result is a pointer to the complete object pointed to by expression.



--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
maxim1000
Дата 9.10.2012, 22:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 17
Всего: 110



Цитата(borisbn @  9.10.2012,  19:42 Найти цитируемый пост)
maxim1000, не подскажешь, ты до этого методом тыка дошёл или прочитал где ?

когда-то обсуждали вопросы для собеседований, вот со мной и поделились smile


--------------------
qqq
PM WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1140 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.