【问题标题】:How to have a Struct with template with a class如何有一个带模板的结构和一个类
【发布时间】:2010-09-06 06:07:17
【问题描述】:

用这段代码(只是一类测试):

typedef unsigned short UInt16;

template<class T>
class CClass
{
public:
    SValue* getNewSValue(void);
private:
    typedef struct {
        T *mValue;
        T *next;
        T *previous;
        UInt16 index;
    } SValue;
};

template<typename T>
SValue* CClass<T>::getNewSValue(void)
{
    return new SValue;
}

我有以下错误:

错误 C2143:语法错误:缺失 ';'在'*'之前

错误 C4430:缺少类型说明符 - int 假定。注意:C++ 没有 支持默认整数

可以在类中使用结构吗?如果我从类中声明结构,则模板看不到模板T

【问题讨论】:

  • +1: 格式很好的问题

标签: c++ templates struct


【解决方案1】:

$9.2/2- 关键是来自 C++ Standard03 的以下引用

`在类说明符的结束 } 处,类被认为是完全定义的对象类型(3.9)(或完整类型)。在类成员规范中,类在函数体、默认参数和构造函数 ctor-initializers(包括嵌套类中的此类内容)中被认为是完整的。 否则它在其自己的类成员规范中被认为是不完整的。

不知道UINT16 是什么,但以下应该可以工作

template<class T> 
class CClass 
{ 
private: 
    typedef struct { 
        T *mValue; 
        T *next; 
        T *previous; 
        short int index;                      // Replacing with int for illustration only
    } SValue; 
public:
    SValue* getNewSValue(void); 
private: 
}; 

编辑 3:*** 来到那里试图使更改 BOLD(无论如何我都应该删除)

template<class T> typename CClass<T>::SValue* CClass<T>::getNewSValue(void) 
{ 
    return new SValue; 
}

int main(){
    CClass<int> s;
    s.getNewSValue();
}

【讨论】:

  • getNewSValue 定义中的typename 关键字的作用是什么?那是因为 SValue 是未命名的,我们必须使用 typedef 名称来引用它?
  • @Cedric 如果我们省略typename,它将被解析为类CClass&lt;T&gt; 的一个名为SValue 的成员的定义,没有为其指定类型:tempate&lt;class T&gt; Class&lt;T&gt;::SValue;。后面的标记将是垃圾并被编译器作为语法错误拒绝。这一切都是因为如果编译器在解析时无法查找名称(即它还不知道T 是什么,所以它无法查找SValue),默认情况下会假定非类型。如果您输入typename,则SValue 被正确地视为成员getNewSValue 的类型名。
  • 您放置的代码会生成以下错误:“错误 C2244: 'CClass::getNewSValue' : 无法将函数定义与现有声明匹配”
  • 有一段时间你把我和三重指针(*)搞混了。我认为应该是 SValue* 而不是 SValue***
  • @hype:是的,这是我的错。我试图让它大胆,然后决定不这样做。所以我手动删除了前导 ** 但忘记了尾随 :( 相应地编辑了我的帖子
【解决方案2】:

由于成员函数定义在全局范围内,您需要使用CClass:: 限定其返回类型以引用类范围内的名称。此外,在引用嵌套在模板中的类型名时,需要使用 typename 关键字。

template<typename T>
typename CClass<T>::SValue* CClass<T>::getNewSValue(void)

此外,嵌套结构是未命名的。请注意,在 C++ 中,类和结构具有专有名称,而 typedef 名称不是类名。避免使用 typedef 会更好。

struct SValue {
    T *mValue;
    T *next;
    T *previous;
    UInt16 index;
};

【讨论】:

  • 这很冗长:-),但是 Potatos 你的代码会生成以下错误,就行了: typename CClass::SValue* CClass::getNewSValue(void) ERROR - --> "error C2899: typename cannot be used outside a template declaration"
  • @okami:保留template&lt; typename T &gt; 部分。对于不太冗长的语法,请在 class {} 范围内定义函数。那么typename 和资格(在类本地类型上)就不需要了。
【解决方案3】:

当您声明getNewSValue 的返回类型时,您的struct 似乎没有定义。

这样你就没有那个错误了:

template<class T>
class CClass
{
public:
    SValue* getNewSValue(void);
private:
    typedef struct {
        T *mValue;
        T *next;
        T *previous;
        UInt16 index;
    } SValue;
};

template<typename T>
SValue* CClass<T>::getNewSValue(void)
{
  return new SValue;
}

您还必须限定SValue 返回类型,因为当您使用它来定义getNewSValue 时,它嵌套在CClass 中。

【讨论】:

    【解决方案4】:

    getNewSValue()之前声明SValue

    template<class T> 
    class CClass 
    { 
    private: 
        typedef struct { 
            T *mValue; 
            T *next; 
            T *previous; 
            UInt16 index; 
        } SValue; 
    public: 
        SValue* getNewSValue(void); 
    }; 
    

    另外,请确保已定义 UInt16

    【讨论】:

      【解决方案5】:

      试试这个怎么样?它适用于 VS2008

      template<class T>
      class CClass
      {
      private:
          typedef struct {
              T *mValue;
              T *next;
              T *previous;
              __int16 index;
          } SValue;
      
      public:
          SValue* getNewSValue(void)
          {
              return new SValue;
          }
      };
      

      【讨论】:

        【解决方案6】:

        SValue-Type 在 CClass 命名空间内。您需要在类外完全限定类型名。

        template<typename T>
        CClass<T>::SValue* CClass<T>::getNewSValue(void)
        

        此外,如果 SValue 由公共方法返回,您应该将其设为公共。

        【讨论】:

          【解决方案7】:

          作为记录,一旦调用getNewSValue(),这些都不会编译(至少在 GCC 4.2 上)。由于它是返回指向私有类型的指针的公共方法,因此您将收到一个编译错误,指出 SValue is private

          为了使其工作,您要么需要公开 SValue,要么将 getNewSValue() 的返回值类型更改为 void*,因为您似乎正在尝试使 SValue 成为不透明类型。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-05-06
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-12-22
            相关资源
            最近更新 更多