【问题标题】:Why i am getting error while executing with the following code?为什么在使用以下代码执行时出现错误?
【发布时间】:2011-07-19 12:00:36
【问题描述】:

技术 1 -> 导致错误

我有三个文件MyType.h, MyType.cpp & main.cpp

MyType.h

#ifndef MYTYPE_H
#define MYTYPE_H

#include<iostream>
using namespace std;

template <class T,int iMax>

class A{
    T iData;
public:
    void vSetData(T iPar1);
    void vDisplayData();
};
#endif

MyType.cpp

#include"MyType.h"

void A::vSetData(T iPar1){
    if(iPar1 <= iMax)
        iData = iPar1;
}
void A::vDisplayData(){
    cout<<"\nData is: "<<iData<<endl;
}

main.cpp

#include"MyType.h"

typedef A<int,20> MyType;

int main(){
    int x = 12;
    MyType obj;
    obj.vSetData(12);
    obj.vDisplayData();
    return 0;
}

错误:10 个错误。它们如下:-

  • mytype.cpp(2) : 错误 C2955: 'A' : 使用类模板需要模板参数列表
  • mytype.h(9) : 参见 'A' 的声明
  • mytype.cpp(2) : 错误 C2955: 'A' : 使用类模板需要模板参数列表
  • mytype.h(9) : 参见 'A' 的声明
  • mytype.cpp(2):错误 C2065:'T':未声明的标识符
  • mytype.cpp(2):错误 C2146:语法错误:标识符“iPar1”之前缺少“)”
  • mytype.cpp(2):错误 C2761:'void A::vSetData(T)':不允许成员函数重新声明
  • mytype.cpp(2):错误 C2059:语法错误:')'
  • mytype.cpp(2):错误 C2143:语法错误:缺少 ';'在“{”之前
  • mytype.cpp(2) : 错误 C2447: '{' : 缺少函数头(旧式正式列表?)
  • mytype.cpp(6) : 错误 C2955: 'A' : 使用类模板需要模板参数列表
  • mytype.h(9) : 参见 'A' 的声明
  • mytype.cpp(6):错误 C2509:“vDisplayData”:成员函数未在“A”中声明
  • mytype.h(9) : 参见 'A 的声明

技术 2 -> 工作正常。

AboveCodeInOneFile.cpp

#include<iostream>
using namespace std;

template <class T,int iMax>

class A{
    T iData;
public:
    void vSetData(T iPar1){
        if(iPar1 <= iMax)
            iData = iPar1;
    }
    void vDisplayData(){
        cout<<"\nData is: "<<iData<<endl;
    }
};

typedef A<int,20> MyType;

int main(){
    int x = 12;
    MyType obj;
    obj.vSetData(12);
    obj.vDisplayData();
    return 0;
}

请让我知道我在 Technique 1

中犯了什么错误

【问题讨论】:

标签: c++ class templates


【解决方案1】:

定义模板类时,编译器必须看到方法定义。所以它们必须在头文件中。

编辑

您必须包含方法实现,以便编译器看到。您可以通过从另一个“MyType_impl.h”文件中包含它们来做到这一点:

template <class T, int iMax>
void A<T, iMax>::vDisplayData()
{
  cout<<"\nData is: "<<iData<<endl;
}

【讨论】:

  • 或显式实例化,但这不是错误所在。
  • 解决问题的任何其他方式。还有一个疑问,在头文件中定义方法是不是一个好方法?
【解决方案2】:

每个方法定义都需要在其上方进行完整的类名修饰:

template <typename T>
void A<T>::vSetData(T iPar1){
    if(iPar1 <= iMax)
        iData = iPar1;
}

template <typename T>
void A<T>::vDisplayData(){
    cout<<"\nData is: "<<iData<<endl;
}

当你这样做时,你会得到其他编译错误,原因是 Abhineet 概述的。为了解决这个问题,你可以把我写的定义放在头文件中,在类声明的下面,或者你可以把它放在另一个头文件(MyType_Inc.h)中,并在类声明头文件中包含 /that/ 头文件

【讨论】:

    【解决方案3】:

    技术 1 不适用于模板。不要使用它。

    将模板视为实际功能的蓝图。蓝图本身不可编译。只有当您替换模板参数 (&lt;class T,int iMax&gt;) 时,才会构建实际函数。因此,编译器在尝试从模板构建函数时必须看到蓝图。为了查看蓝图,它们必须完全驻留在头文件中。

    【讨论】:

      【解决方案4】:

      定义成员函数时,必须重复模板参数

      template <class T,int iMax>
      void A<T, iMax>::vSetData(T iPar1)
      {
           if(iPar1 <= iMax)
               iData = iPar1; 
      } 
      

      这样可以避免编译错误。

      下一个问题是.cpp 文件中定义的模板只能在该文件中使用。如果你想在其他地方使用它们,你真的应该把定义放在标题中。

      【讨论】:

        【解决方案5】:

        您的第一个版本有两个问题。

        在类外实现类模板的成员时,需要将其声明为模板:

        template <class T,int iMax>
        void A<T,iMax>::vSetData(T iPar1){
            if(iPar1 <= iMax)
                iData = iPar1;
        }
        

        此外,函数定义需要在任何实例化模板的编译单元中可用。在实践中,这意味着您通常应该内联定义它们(在类模板定义内部,或在其外部但在头文件中并声明为inline)。像你一样在源文件中简单地定义它们会导致链接错误。

        【讨论】:

          猜你喜欢
          • 2023-01-05
          • 1970-01-01
          • 2015-12-13
          • 2019-09-20
          • 2013-01-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多