代码之家  ›  专栏  ›  技术社区  ›  smerlin

有没有一种方法可以在不破坏封装的情况下为模板类(对于所有类型)使用单个静态变量

  •  3
  • smerlin  · 技术社区  · 16 年前

    我需要一种方法为我的模板类的所有类型拥有一个单一的静态变量。

    template <class T> class Foo { static Bar foobar;};

    好吧,上面这一行将为每种类型生成一个名为foobar的bar对象 T ,但这不是我想要的,我基本上想要一种方法来声明类型栏的变量,所以类型栏的每个对象 Foo 可以访问相同的 foobar 变量,独立于 T .

    我试图用另一个类来存储私有的东西,但这行不通,因为标准不允许像这样的东西 template <class T> friend class Foo<T>;

    因此,显而易见的解决方案(如下所示)是拥有一个全局变量 Bar foobar ,但这显然违反了信息隐藏概念(适当封装的概念):

    Bar Foo_DO_NOT_TOUCH_THIS_PLEASE_foobar;
    template <class T> class Foo { static Bar& foobar;};
    template <class T> Bar& Foo<T>::foobar=Foo_DO_NOT_TOUCH_THIS_PLEASE_foobar;
    

    当然,您可以另外使用一个详细的名称空间(这正是我目前正在做的),但是是否有其他方法可以真正禁止用户乱搞您的私有静态变量?

    另外,当您必须以类似的方式声明许多静态方法时,这个解决方案会变得非常混乱,因为您很可能必须扩展使用friend关键字,例如 friend RetType Foo_detail::StaticFunc(ArgT1, ArgT2) .

    而且用户不会有一个好的界面,因为他们不能像以前那样使用这些功能 Foo<T>::someFunc() 但相反,他们必须打电话给 Foo_static::someFunc() (如果使用命名空间 Foo_static 用于公共静态功能)。

    那么有没有其他解决方案不破坏封装和/或不引入大量语法开销?

    编辑: 基于你所有的想法,我尝试了以下方法,它按预期工作:

    typedef int Bar;
    template <class T> class Foo;
    
    class FooBase
    {
        static Bar foobar;
        public:
            template <class T> friend class Foo;
    };
    Bar FooBase::foobar;
    
    template <class T> class Foo : public FooBase
    {
        public:
        using FooBase::foobar;
    };
    

    此解决方案具有用户无法从foobase继承的好处。

    4 回复  |  直到 16 年前
        1
  •  9
  •   Peter Alexander    16 年前

    可能继承静态成员?

    class OneBarForAll
    {
    protected:
      static Bar foobar;
    };
    
    template <class T>
    class Foo : public OneBarForAll
    {
    
    };
    

    许多 Foo<T> 将生成,但只有一个 OneBarForAll .

    与此相关的一个潜在问题是,没有任何东西阻止代码的其他用户从继承 巴纳福尔 修改 foobar 不管怎样。

    理想情况下,您需要模板朋友,因为这最好地描述了您的设计的访问要求,但是C++目前不允许。

        2
  •  4
  •   rmn    16 年前

    语法

    template <class T> friend class Foo<T>;
    

    template <class T> friend class Foo;
    

    (这意味着foo的每个实例都是您在其中定义它的类的朋友)

    所以也许你可以选择你之前排除的解决方案。

        3
  •  3
  •   KitsuneYMG    16 年前

    你可以这样做:

    struct Base {
      static Foo foo;
    };
    //init foo here
    
    template<typename T>
    struct Derived : Base {
    ...
    };
    ...
    Derived<Bar>::foo;
    

    它在g++中工作

        4
  •  1
  •   Derrick Turk    16 年前

    为什么不从非模板基类继承?