【问题标题】:Inheriting from a template class, using a type defined in the derived class从模板类继承,使用派生类中定义的类型
【发布时间】:2011-05-08 13:15:47
【问题描述】:

我正在尝试使用派生类中定义的类型从模板类继承。 这个我试过了,还是不行。

class A : std::vector<A::B>
{
    enum B { foo, bar };
};

有没有一种优雅的方式来做到这一点?

编辑:我知道如果 B 定义较早,它会起作用。但我正在寻找一种允许将类型 B 封装在 A 类中的解决方案。

【问题讨论】:

  • 你想做什么?你的目标是什么?在不知情的情况下,不可能告诉你这样做的“优雅方式”。

标签: c++ templates inheritance


【解决方案1】:

您不能在 C++03 中转发声明枚举。只需将向量作为成员并手动转发即可使用正常组合。

【讨论】:

    【解决方案2】:

    您必须先定义enum B,然后才能使用它来继承。

    另外,您不是从标准vector 继承的,是吗?

    【讨论】:

    • 我知道,但我希望 B 类型在 A 类内部,而不是在全局范围内。是的,在这个例子中我的意思是std::vector,这是个问题吗?
    • @otibom:嗯,它没有虚函数,包括没有虚析构函数,所以从它继承而不是仅仅让它成为一个数据成员是没有意义的。大多数人都有一个“详细信息”命名空间,他们会在其中抛出不属于此类内容的预期 API 一部分的垃圾。
    • 哦,是的,但这只是一个例子。另外,这里是私有继承。
    • @DeadMG:“这有点毫无意义” - 如果您使用继承的唯一目的是动态多态性,那么它毫无意义。但是私有继承也是如此。
    • @Steve:私有多态继承当然不是毫无意义的——它允许类将自身引用到另一个需要特定接口的类,而不会将该接口暴露给世界。私有实现继承不提供私有组合不提供的任何东西,除了在使用继承/组合对象时保存一些字符(只要您的类不是模板),但会引入问题中的问题而且,在我看来,这使得这两个类之间的关系稍微不那么清晰了。
    【解决方案3】:

    在我看来,最好的(当然是间接的)解决方案是使用组合而不是继承:

    class A
    {
        enum B { foo, bar };
        std::vector<B> bs;
    };
    

    如果出于某种原因您需要(或确实想要)使用私有继承将向量嵌入到您的对象中,则需要在命名空间范围内的类之前定义类型,因为类型不能在它们被使用之前被使用宣布。如果它们不打算被类的用户访问,并且您不想污染包含您的类的命名空间,那么您可以将它们放在命名空间中以表明它们是实现细节:

    namespace details
    {
        enum B { foo, bar };
    }
    
    class A : std::vector<details::B>
    {
        typedef details::B B;               // if you don't want to write "details::B" everywhere
        static const B foo = details::foo;  // if you don't want to write "details::foo" everywhere
        // and so on.
    };
    

    【讨论】:

      【解决方案4】:

      感谢大家的回答,但我刚刚找到了一个(编辑:不好的)解决方案:

      namespace
      {
      enum B_type { foo, bar };
      }
      
      class A : std::vector<B_type>
      {
          typedef value_type B;
      };
      

      【讨论】:

      • 匿名命名空间没有做任何有用的事情,因为它用 B_type 污染了封装的命名空间,就像命名空间根本不存在一样。匿名命名空间在头文件中毫无意义,仅供参考。
      • 比命名空间污染更糟糕:这意味着class A 将在每个编译单元中包含不同类型的成员,从而打破“单一定义规则”。如果你真的坚持在这里使用继承而不是组合,那么将额外的类型定义放在命名命名空间中(details 是命名空间的常用名称,其中包含出于某种原因不能是私有类的实现细节成员)。
      猜你喜欢
      • 2022-10-15
      • 2018-05-23
      • 1970-01-01
      • 1970-01-01
      • 2016-08-02
      • 2011-11-30
      • 1970-01-01
      • 1970-01-01
      • 2022-01-03
      相关资源
      最近更新 更多