Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Вызов функции NULL-pointer'а


Автор: borisbn 24.11.2010, 00:40
День добрый.
Есть такая распространённая задача: в конструкторе класса передаётся объект, функции которого вызываются в других функциях класса.
Псевдокод:
Код

class ИмяКласса {
    ИмяКласса( ТипОбъекта * объект ) : m_объект( объект ) {}
    void foo() { if ( объект ) объект->foo(); }
...
    ТипОбъекта * m_объект;

В случае, когда объект ( указатель на него ) ни в каких случаях не может быть нулём есть смысл сделать ссылкой. В случае, когда объект может быть не создан ( NULL ) приходится проверять: if ( объект ).
Так вот, хочу избавиться от if ( объект ). как-то так
Код

#include <УниверсальнаяОбёрткаНадОбъектом.h>
class ИмяКласса {
    ИмяКласса( ТипОбъекта * объект ) : m_универсальнаяОбёрткаНадОбъектом( объект ) {}
    void foo() { m_универсальнаяОбёрткаНадОбъектом.foo(); }
...
    УниверсальнаяОбёрткаНадОбъектом< ТипОбъекта > m_универсальнаяОбёрткаНадОбъектом;

Не могу сообразить как это сделать. И возможно ли это вообще.

P.S. УниверсальнаяОбёрткаНадОбъектом ессно не должна знать о классе ТипОбъекта.
P.P.S. #define SAFE_CALL( объект, ф-ция, парамтеры ) не предлагать, т.к. не люблю макросы и код становится не читаемым.

Автор: boostcoder 24.11.2010, 01:09
тернарное выражение?

Автор: azesmcar 24.11.2010, 05:54
Код

template <typename T>
class safe_wrapper
{
private:
    T* object;
public:
    safe_wrapper(T* o) : object(o) {}
    T* operator -> ()
    {
        if (!object)
            throw std::runtime_error("null pointer exception");
        return object;
    }
};

?

Автор: borisbn 24.11.2010, 09:43
boostcoder, не совсем ( вернее совсем нет smile ). Выражение типа
Код

(объект) ? объект->foo() : void()

ничем не лучше, чем
Код

if ( объект ) объект->foo();

я просто хочу сделать класс-обёртку над любым указателем на объект, который бы транслировал вызовы функций объекту, если он не 0, и НИЧЕГО не делал бы в другом случае.

azesmcar, я рассматриваю случай, когда не созданный объект это НЕ ИСКЛЮЧИТЕЛЬНАЯ, а НОРМАЛЬНАЯ ситуация. Чтобы не дать возможность создавать 0-й объект лучше использовать ссылку.
Т.о. я хочу что-то типа:
Код

template <typename T>
class safe_wrapper
{
private:
    T* object;
public:
    safe_wrapper(T* o) : object(o) {}
    вызов_любой_функции_объекта()
    {
        if ( object )
            вызов_этой_функции();
        else
            do_nothing();
    }
};

...

safe_wrapper< ObjType > o_wrap( obj );
o_wrap.foo( 1, "qwerty" );
o_wrap.bar( x, y, z );


Наверное, это просто невозможно, но чем чёрт не шутит ... Может всемирный разум что-нибудь придумает smile

Автор: azesmcar 24.11.2010, 10:06
Цитата(borisbn @  24.11.2010,  09:43 Найти цитируемый пост)
azesmcar, я рассматриваю случай, когда не созданный объект это НЕ ИСКЛЮЧИТЕЛЬНАЯ, а НОРМАЛЬНАЯ ситуация. Чтобы не дать возможность создавать 0-й объект лучше использовать ссылку.

Не думаю, что это возможно. Из кода вызывается функция и если программа продолжает свое выполнение эта функция  должна что-то выполнить. Можно выкрутиться макросами или совершать вызов через указатель на функцию, но я бы так не делал.

Цитата(borisbn @  24.11.2010,  09:43 Найти цитируемый пост)
Может всемирный разум что-нибудь придумает

Я честно пробовал, не получилось smile  smile 

Автор: borisbn 24.11.2010, 10:13
Цитата(azesmcar @  24.11.2010,  10:06 Найти цитируемый пост)
Можно выкрутиться макросами или совершать вызов через указатель на функцию, но я бы так не делал

Если это будет выглядеть как
Код

obj_wrap.foo( параметры );

то можно, конечно, и макросами, хотя не хочется.
А как сделать через указатель на функцию - что-то не соображу.

Автор: azesmcar 24.11.2010, 10:21
Цитата(borisbn @  24.11.2010,  10:13 Найти цитируемый пост)
А как сделать через указатель на функцию - что-то не соображу. 

как-то так..и перегрузить для нескольких аргументов, но это извращение.
Код

template <typename T>
void safe_call(T* ptr, void (T::*function)())
{
    if (ptr)
        (ptr->*function)();
}

Автор: Леопольд 24.11.2010, 13:42
Цитата(azesmcar @  24.11.2010,  10:21 Найти цитируемый пост)
как-то так..и перегрузить для нескольких аргументов, но это извращение.
Код
template <typename T, typename ... Args>
void safe_call(T* ptr, void (T::&function)(Args...), Args ... args)
{
    if (ptr)
        ptr->function(args ...);
}

Когда ж, уже новый стандарт примут...

Автор: azesmcar 24.11.2010, 14:31
Леопольд

Все равно извращение smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)