【问题标题】:Inherit template class with nested class使用嵌套类继承模板类
【发布时间】:2019-01-04 01:06:32
【问题描述】:

我想创建一个继承自模板类 A 的类 B。我希望 B 的嵌套类 E 成为此继承中的模板参数。更直观:

template <class T>
class A {
}

class B : public A<B::E> {
    class E {
        int x;
    }
}

class C : public A<C::E> {
    class E {
        int x;
        int y;
    }
}

我认为问题在于编译器在处理 B 的声明时并不知道 B 类将有一个嵌套类 E,因为我收到了错误:

“B”中没有名为“E”的成员

我已经看到了这个similar question,但我想确认在放弃这种方法之前没有直接解决这个冲突的方法。

谢谢!

【问题讨论】:

标签: c++ templates inheritance inner-classes


【解决方案1】:

我觉得不能直接做。

一种明显的方法是在其他命名空间中定义B::EC::E(至少将它们排除在全局命名空间之外),然后在“父”类中使用它们:

template <class T>
class A { /* ... */ };

namespace B_detail {
    class E { /* … */ };
}

class B : public A<B_detail::E> { /* ... */ };

namespace C_detail {
    class E { /* ... */ };
}

class C : public A<C_detail::E> { /* ... */ };

根据具体情况,您很有可能还需要/想要声明 B/C 的 *_detail::Efriend

【讨论】:

    【解决方案2】:

    我能想到的最接近的方法是使用基类。

    template <class T>
    class A {
    };
    
    class B; // forward declaration of ::B
    namespace detail { 
    class B { 
        friend class ::B;
        class E {
            int x;
        };
    };
    } /* namespace detail */
    
    class B : public A<detail::B::E> {
    };
    

    【讨论】:

      【解决方案3】:

      正如其他人所说,您不能对嵌套类进行前向声明。

      所以您可以使用将您的 nested 类放入 namespace 中。或者,您可以只删除任何嵌套,但必须提供不同的名称。

      这是一个演示这两种方式的示例。如果您不需要前向声明,代码可能会更简单一些。

      #include <memory>
      
      template <class T>
      class A {
      public:
          A();
      
          // Demonstrate a possible way that T could be used.
          std::unique_ptr<T> t;
      };
      
      template <class T>
      A<T>::A() : t(std::make_unique<T>())
      {
      }
      
      // Using a forward declared (top level) class...
      class B : public A<class BE> {
      };
      
      class BE {
      public:
          int x;
      };
      
      // Using a forward declared class inside a namespace...
      namespace C_details
      {
          class E;
      }
      
      class C : public A<C_details::E> {
      };
      
      namespace C_details
      {
          class E {
          public:
              int x;
              int y;
          };
      }
      
      
      int main()
      {
          B b;
          b.t->x = 3;
      
          C c;
          c.t->y = 4;
      
          return 0;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-05-23
        • 1970-01-01
        • 1970-01-01
        • 2011-06-19
        • 1970-01-01
        • 2017-02-25
        • 1970-01-01
        相关资源
        最近更新 更多