C ++ Получить тип класса внутри статической функции - PullRequest
6 голосов
/ 07 ноября 2011

Внутри статической функции-члена мне нужно получить тип.

class MyClass
{
     public:
         static void myStaticFunc();
     ...
};

И тогда в реализации я хочу иметь:

void MyClass::myStaticFunc()
{
     // Get MyClass as a type so I can cast using it
     (get_type_from_static_function()*)someOtherVariable;
}

Это вообще возможно? Обычно я использовал бы что-то из typeinfo для объекта, но у меня нет this для работы.

Я не хочу просто использовать (MyClass*), потому что это происходит внутри макроса, и я хотел бы сделать его как можно более простым, чтобы его можно было вызывать без имени класса.

Если это помогает, я использую QT, но не могу найти макросы для получения текущего класса. Это не обязательно должно быть программно - это может быть макрос.

ура!

EDIT: Вот актуальная функция макроса:

#define RPC_FUNCTION(funcName) \
static void rpc_##funcName(void* oOwner, RpcManager::RpcParamsContainer params){ ((__class__*)oOwner)->funcName(params); }; \
void funcName(RpcManager::RpcParamsContainer params);

Затем я вызываю RPC_FUNCTION(foo) в объявлении класса. Я хочу, чтобы __class__ было тем объявлением класса, в котором я нахожусь. Я хорошо знаю, что могу просто добавить className после funcName, но я хочу сделать это как можно более простым, когда на самом деле его используем. Мой RPC-менеджер вызывает rpc_foo и передает указатель на объект класса, в котором я его объявил. По сути, мне нужно знать, как определить фактический класс этого параметра void *.

Ответы [ 6 ]

1 голос
/ 09 октября 2014

В Visual Studio 2012 вы можете использовать этот трюк, но он не будет работать в gcc, по крайней мере сейчас.

        template<typename base_t>
        static auto GetFunctionBaseType(void(base_t::*)())->base_t;

        struct TBase
        {
            template<typename T> void GetBaseType();
            typedef decltype(GetFunctionBaseType(&GetBaseType<void>)) this_t;

            static void rpc_func1(void * ptr)
            {
                ((this_t*)ptr)->func1();
            }
        };
1 голос
/ 07 ноября 2011

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

T x;

, тогда тип T должен быть известен во время компиляции.Не существует такого понятия, как "T_from_user() x;", при котором фактический тип переменной определяется во время выполнения.Язык просто не спроектирован таким образом.

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

0 голосов
/ 07 ноября 2011

Поиск макроса функции?Это макрос, который расширяется до текущего имени функции.

 __FUNCTION__
0 голосов
/ 07 ноября 2011

Кажется, у вас есть несколько несвязанных классов, которые имеют несколько общих методов (те, которые могут быть отправлены в качестве аргумента funcName в вашем примере).

Вместо того, чтобы иметь эти несвязанные классы, рассмотрим полиморфный подход. Например, допустим, что вы поддерживаете функции func1 и func2, тогда вы можете решить это следующим образом:

class BaseClass {
public:
    virtual void func1(RpcManager::RpcParamsContainer args) = 0;
    virtual void func2(RpcManager::RpcParamsContainer args) = 0;
};

class MyClass1 : public BaseClass {
public:
    virtual void func1(RpcManager::RpcParamsContainer args) { /* func1 implementation here */ }
    virtual void func2(RpcManager::RpcParamsContainer args) { /* func2 implementation here */ }
};

class MyClass2 : public BaseClass {
public:
    virtual void func1(RpcManager::RpcParamsContainer args) { /* func1 implementation here */ }
    virtual void func2(RpcManager::RpcParamsContainer args) { /* func2 implementation here */ }
};

С вышеописанным дизайном вы можете передавать BaseClass*, и вы можете вызывать func1 или func2 без каких-либо преобразований, и компилятор найдет правильную версию для вызова. Например, в вашем макросе вы можете сделать что-то вроде этого:

#define RPC_FUNCTION(funcName) static void rpc_##funcName(BaseClass* oOwner, RpcManager::RpcParamsContainer params){ oOwner->funcName(params); };

Надеюсь, это поможет!

0 голосов
/ 07 ноября 2011

То, что вы хотите сделать, называется отражением.Он был реализован в .NET (я не знаю, может быть, и в Java) и будет реализован в будущих стандартах C ++.

0 голосов
/ 07 ноября 2011

Нет, статический метод может видеть только статические члены класса.Для него не имеет смысла обращаться к членам экземпляра (как, например, к стандартным переменным и т. Д.), Поскольку они не существуют, если не создан экземпляр класса.

Похоже, вы хотите что-то вроде Синглтон дизайн шаблона.Это позволяет одновременно существовать только одному экземпляру класса.

Другой способ - создать статический список всех экземпляров класса, а затем в конструкторе класса добавить указатель this.в этот список.Как я уже сказал, статические члены не могут получить доступ к переменным экземпляра, поскольку они могут вообще не существовать.

Я предполагаю, что главный вопрос заключается в следующем: зачем вам нужен доступ к переменной экземпляра из статического члена?Если вам требуется доступ к члену экземпляра, вы должны вызывать функцию в контексте текущего экземпляра, в противном случае вы довольно сильно нарушаете парадигму ООП.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...