【问题标题】:How do I retrieve the type of the base class in C++?如何在 C++ 中检索基类的类型?
【发布时间】:2016-06-18 09:25:45
【问题描述】:

对于这个特定项目,我无法使用 C++11 功能(例如 decltype),因为编译器还不支持它们。我需要能够将当前类作为模板参数提供,最好在没有参数的宏中提供(见下文),无需修饰 class 声明或隐藏花括号等。

class Foo: private Bar<Foo> {
   MAGIC //expands to using Bar<Foo>::Baz; and some others
   public:
      void otherFunction();
      //... the rest of the class
};

理想情况下,我希望它与 Qt 的 Q_OBJECT 宏非常相似,但不引入另一个预编译步骤和相关的生成类。 typeid 可能在运行时有用,但我的目标是在构建时完成所有这些。

如何编写MAGIC 宏,这样我就不需要每次都重复类名了?

【问题讨论】:

  • 这个问题好像是C++03版的“Can I implement an autonomous self member type in C++?
  • 介意我把标题改成base clase吗? 封闭类 听起来像是在嵌套以及外部类的类型。
  • self 问题看起来确实非常相似,但正如您所指出的,它看起来不像任何提议的解决方案都可以在 C++03 中工作。如果标题更清楚,当然要更改标题。
  • 在 C++ 中必须问哪个基类?
  • 我的 2 美分是:这可能是不可能的;而不是强装一个不是为它设计的宏系统,要么运行你的代码,例如通过 perl 脚本;或找到使用 C++ 的不同解决方案(例如,使用唯一的 int 作为模板参数,而不是类型名)。

标签: c++ templates c-preprocessor c++03


【解决方案1】:

怎么样:

template<typename T>
class Base
{
protected:
    typedef Base<T> MagicBaseType;
    namespace Baz { }
};

class Derived1 : private Base<Derived1>
{
    using MagicBaseType::Baz;
}


class Derived1 : private Base<Derived2>
{
    using MagicBaseType::Baz;
}

或者,如果您无法修改 Base 定义,则使用模板和多重继承

template<typename T>
class Base
{
protected:
    namespace Baz { }
};

template<typename T>
class DerivedTemplate : public T
{
protected:
    typedef typename T BaseType;
}

class Derived : public Base<Derived>, public DerivedTemplate<Base<Derived>>
{
using BaseType::Baz;
}

【讨论】:

    【解决方案2】:

    我认为没有任何语言支持的机制可以从类中提取基类型。您可以使用:

    选项 1

    class Foo: private Bar<Foo> {
    
    #define BASE_TYPE Bar<Foo>
       // Use BASE_TYPE in MAGIC
       MAGIC //expands to using Bar<Foo>::Baz; and some others
    #undef BASE_TYPE
    
       public:
          void otherFunction();
          //... the rest of the class
    };
    

    选项 2

    class Foo: private Bar<Foo> {
    
        typedef Bar<Foo> BASE_TYPE;
    
       // Use BASE_TYPE in MAGIC
       MAGIC //expands to using Bar<Foo>::Baz; and some others
    
       public:
          void otherFunction();
          //... the rest of the class
    };
    

    【讨论】:

    • 你可以通过#defineing BASE_TYPE before类声明来避免冗余,所以你可以说class Foo : private BASE_TYPE
    • 或者保留在课堂上并使用typedef而不是#define,如typdef Bar&lt;Foo&gt; BaseType;
    • @RyanHaining,这就是为什么我在 #undef 之后有 MAGIC 行。
    【解决方案3】:

    如果您真的不关心格式化或编写令人头疼的维护问题,您可以通过让宏获取类型参数来执行此操作而无需重复类型:

    #define MAGIC(BASE) \
    BASE { \
        using BASE::baz;
    
    class Sub : private MAGIC(Base<Foo>)
    
      public:
        void otherFunction();
    };
    

    但这让我对自己感觉很糟糕

    【讨论】:

      【解决方案4】:

      您可以使用“代理”(?)结构来建立继承:

      template <typename S>
      struct Base : public S{ //always public, access is restricted by inheriting Base properly
          using super = S;
      };
      

      用法如下:

      #include <iostream>
      
      template <typename S>
      struct Base : public S { 
          using super = S;
      };
      
      template <typename T>
      class Bar
      {
      public:
          virtual void f() { std::cout << "Bar" << std::endl;  }
      };
      
      class Foo : private Base<Bar<int>>
      {
      public:
          virtual void f() 
          { 
              std::cout << "Foo";
              super::f();  //Calls Bar<int>::f()
          }
      };
      
      class Fii : private Base<Foo>
      {
      public:
          virtual void f() 
          {
              std::cout << "Fii";  
              super::f(); //Calls Foo::f()
          }
      };
      
      
      int main()
      {
          Fii fii;
          fii.f(); //Print "FiiFooBar"
          return 0;
      }
      

      【讨论】:

        猜你喜欢
        • 2011-01-14
        • 2023-04-10
        • 2012-06-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-09-04
        • 1970-01-01
        • 2011-04-27
        相关资源
        最近更新 更多