【问题标题】:C++ Get class type inside static functionC ++在静态函数中获取类类型
【发布时间】:2011-12-23 07:44:37
【问题描述】:

在静态成员函数内部,我需要获取类型。

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 有帮助,但我找不到任何宏来获取当前类。它不一定需要是程序化的 - 它可以是一个宏。

干杯!

编辑: 这是实际的宏功能:

#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__ 成为我所在的任何类声明。我很清楚我可以在 funcName 之后添加 className 但我希望在实际使用它时尽可能简单。我的 RPC 管理器调用 rpc_foo 并将指针传递给我声明它的类的对象。基本上我需要知道如何确定该 void* 参数的实际类。

【问题讨论】:

    标签: c++ class types static


    【解决方案1】:

    在 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();
                }
            };
    

    【讨论】:

      【解决方案2】:

      我相信您的内心要求根本不可能:C++ 是一种静态类型 语言,这意味着所有类型信息都必须在编译时可用(尽管存在运行时多态性) .也就是说,当你说,

      T x;
      

      那么T的类型必须在编译时知道。没有“T_from_user() x;”这样的东西,变量的实际类型是在运行时确定的。语言不是这样设计的。

      通常,如果您提出这样的问题,则表明您以错误的方式解决问题。多态情况的典型解决方案涉及类继承和虚函数,或其他类型的查找表,或实际上任何数量的不同方法。您对预处理器宏的请求也表明有问题。任何编程语言都有其惯用语,偏离这些惯用语通常是个坏主意。

      【讨论】:

      • 有点,我更多地使用它来在宏内转换对象(当前是 void*)。像这样:static void myFunction(void* owner) { // I need to get MyClass so that I can cast it without explicitly writing it. (MyClass*)owner-&gt;myMemberFunction(); }
      • 你为什么不在问题中发布你的实际问题,我们可以看看?越抽象越好;始终假设您为解决问题而做出的任何决定都可能走错了方向。
      • @cleversoap:您可以只为您的类赋予 typedef typedef Myclass SelfType; 并始终将 reinterpret_cast&lt;SelfType*&gt;(owner) 放入您的宏中。
      • 为什么是reinterpret_cast?一个简单的static_cast 就足够了。
      • 那个 typedef 似乎是最好的解决方案。我只是在任何类声明中调用一个 init 宏。感谢您的所有帮助!
      【解决方案3】:

      你想做的事情叫做反射。它是在 .NET 中实现的(我不知道,可能也在 Java 中)并且将在未来的 C++ 标准中实现。

      【讨论】:

      • 我认为问题在于静态类型,而不是缺乏反射。反射略有不同。
      【解决方案4】:

      您似乎有一些不相关的类,它们有许多共同的方法(在您的示例中可以作为 funcName 参数发送的方法)。

      考虑使用多态方法,而不是使用这些不相关的类。比如你支持的函数是func1func2,那么你可以这样算:

      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*,并且您可以调用func1func2 而无需进行任何转换,编译器将找到要调用的正确版本。例如,在您的宏中,您可以执行以下操作:

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

      我希望这会有所帮助!

      【讨论】:

      • 最有可能的是,这些静态函数将用作回调,并且void* 参数无法更改。不过,可以使用相同的方法,只需将 void 指针转换为函数内部的BaseClass*。但是,这会产生运行时成本,这是不必要的,因为 OP 想要的东西可以很容易地静态实现。
      • @Xeo:当然,但在我看来,这是一个更简洁的设计,代码更易于维护。在考虑实施何种解决方案时,性能并不是唯一要使用的指标。​​
      【解决方案5】:

      正在搜索函数宏吗?这是一个扩展为当前函数名的宏。

       __FUNCTION__
      

      【讨论】:

        【解决方案6】:

        不,静态方法只能看到类的静态成员。访问实例成员(如标准变量等)是没有意义的,因为除非类已被实例化,否则它们不存在。

        您似乎想要Singleton 设计模式。这允许一次只存在该类的一个实例。

        另一种方法是拥有一个类的所有实例的静态列表,然后在类构造函数中,将this 指针添加到该列表。正如我所说,静态成员不能访问实例变量,因为它们可能根本不存在。

        我想更大的问题是:为什么需要从静态成员访问实例变量?如果您需要访问实例成员,则应该在当前实例的上下文中调用该函数,否则您将很难打破 OOP 范式。

        【讨论】:

        • 对不起,我应该更清楚。我不想访问任何实例变量。我想要的只是MyClass 类型,而没有明确写出来。
        • 哦,对不起,你想实例化静态成员所属的类的实例吗?
        • 基本上是的——但我不能只写MyClass* foo = new MyClass;
        • 很遗憾,我认为没有办法。不过,您可以将类名作为宏的参数。
        • 是的,我想这就是我要做的。我基本上做了所有这些来避免宏的第二个参数。感谢您的帮助。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-02-04
        • 2012-10-18
        • 1970-01-01
        相关资源
        最近更新 更多