【问题标题】:static member definition with template base class带有模板基类的静态成员定义
【发布时间】:2011-07-27 08:43:10
【问题描述】:

有一个基类:

template<class T_CLASS>
class TBase
{
  protected:
    static CSomeClass m_objSomeClass;

  public:
    inline void Set(CSomeClass f_objSomeClass) { m_objSomeClass = f_objSomeClass; }
};

还有一些子类都有自己的静态成员m_objSomeClass。我尝试通过模板化基类来做到这一点。

class CSub1 : public TBase<CSub1>
{
   //...
};

class CSub2 : public TBase<CSub2>
{
  //...
};

这个的定义是什么样的?甚至可能吗?我尝试了一些......但没有奏效:

template<class T_CLASS>
CSomeClass TBase<T_CLASS>::m_objSomeClass;

//In fact the next one worked in Visual Studio; 
// but not in with the armcc where I need it.
CSomeClass TBase<CSub1>::m_objSomeClass;
CSomeClass TBase<CSub2>::m_objSomeClass;

有什么建议吗?谢谢,米尔科

【问题讨论】:

  • 第一种方法应该有效:template &lt;typename T&gt; CSomeClass TBase&lt;T&gt;::m_objSomeClass;,所以一定有一些你没有在代码中显示的东西。 CSomeClass 是否依赖于类型参数?
  • 我将定义移动到另一个源文件,最后它正在正确编译和链接......我仍然不知道之前出了什么问题。 CSomeClass在A.hpp中,Base和Sub类在B.hpp中,其中包括A.hpp,定义在B.cpp中。无论如何...感谢您的帮助!
  • 定义必须可访问在哪里使用该字段。这是一个 templated 定义,如果您在 cpp 文件中提供它,那么编译器将不会实例化静态成员
  • @David Rodríguez,您能详细解释一下吗?现在定义在 D.cpp 中 - 因此它在 cpp 文件中提供,并且一切正常。如果有的话,我看不出静态成员的模板定义和非模板定义之间的区别。
  • 有一个很长的解释,但归根结底是如果你没有在头文件中提供定义并且另一个cpp用新类型实例化你的模板,那么编译器将不会实例化该静态成员为您(它没有实例化的定义)。这与您应该在标头中为模板提供函数定义的原因完全相同,并且可以以完全相同的方式避免它(在 cpp 中提供它并为您需要的所有类型强制实例化),但这会消除通用性: 新代码不能使用不同的参数。

标签: c++ templates static-members derived-class


【解决方案1】:
template<>
CSomeClass TBase<CSub1>::m_objSomeClass;
template<>
CSomeClass TBase<CSub2>::m_objSomeClass;

是正确的方法之一,如果你想明确地为像CSub1CSub2 这样的实体类定义static 成员。 Demo.

编辑:常规方式是定义为:

template<class T_CLASS>
CSomeClass TBase<T_CLASS>::m_objSomeClass;

两种方式都可以达到目的。

【讨论】:

  • 这在 Visual Studio 中运行良好,但使用 armcc 编译器时,我再次遇到链接器错误(“未定义符号”)。我不知道 ideone.com,谢谢 :)
  • @Mirco,它应该可以正常工作。您是否检查过您是否在定义 static 成员的任何位置正确编译/链接文件? (顺便说一句,ideone 只是一个供小型 sn-ps 运行的在线编译器)。
  • 应该正确编译和链接...有没有办法隐式定义静态成员?这有什么问题吗:template&lt;class T_CLASS&gt; CSomeClass TBase&lt;T_CLASS&gt;::m_objSomeClass;
  • @Mirco,不,这没有错。唯一的区别是,只有当您在代码中对它们进行实际引用时,它们才会被实例化。否则完全没问题。
  • 不是定义静态成员的标准方式。标准方法将是 OP 显示的第一种方法。这段代码的语义完全不同,您正在定义静态成员函数的specializations,这将迫使您为每个实例化类型定义这种特殊化,否则您将收到链接器错误。
【解决方案2】:

还有一些子类都有自己的静态 成员 m_objSomeClass。我尝试通过模板化基类来做到这一点。

如果您只想实现单独的静态成员,则不需要子类,您可以从 TBase 实例化,它们将具有单独的静态成员,因为从模板生成的每个模板类都有自己的任何副本静态变量或成员,见下面的例子(例子用 VS2008 和 gcc 编译得很好):

struct CSomeClass {
    CSomeClass(int i):m_i(i){}
    int m_i;
};

template<class T_CLASS>
class TBase
{
  protected:
    static CSomeClass m_objSomeClass;

  public:
    inline void Set(CSomeClass f_objSomeClass) { m_objSomeClass = f_objSomeClass; }
};

class CSub1
{

};

class CSub2
{
};

template<class T_CLASS>
CSomeClass TBase<T_CLASS>::m_objSomeClass = CSomeClass(0);

int main()
{
    TBase<CSub1> tb1;
    TBase<CSub2> tb2;

    //tb1 and tb2 have separate static member after instantiated from tempalte class TBase
    tb1.Set(CSomeClass(1)); //tb1::m_objSomeClass now is 1
    tb2.Set(CSomeClass(2)); //tb2::m_objSomeClass now is 2
}

【讨论】:

    【解决方案3】:

    Mirco,因为你真的需要一个子类,我已经修改了我的例子,所以你有子类并且你有单独的静态成员函数,见下文(这个例子用 VS2008 和 gcc 编译得很好):

    struct CSomeClass {
        CSomeClass(int i):m_i(i){}
        int m_i;
    };
    
    template<class T_CLASS>
    class TBase
    {
      protected:
        static CSomeClass m_objSomeClass;
    
      public:
        inline void Set(CSomeClass f_objSomeClass) { m_objSomeClass = f_objSomeClass; }
    };
    
    class CSub1 : public TBase<CSub1>
    {
    
    };
    
    class CSub2 : public TBase<CSub2>
    {
    };
    
    template<class T_CLASS>
    CSomeClass TBase<T_CLASS>::m_objSomeClass = CSomeClass(0);
    
    int main()
    {
        TBase<CSub1> tb1;
        TBase<CSub2> tb2;
    
        //tb1 and tb2 have separate static member after instantiated from tempalte class TBase
        tb1.Set(CSomeClass(1)); //tb1::m_objSomeClass now is 1
        tb2.Set(CSomeClass(2)); //tb2::m_objSomeClass now is 2
    }
    

    【讨论】:

      猜你喜欢
      • 2017-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多