为什么我在使用以下代码执行时出错?

时间:2011-07-19 12:00:37

标签: c++ class templates

技术1 - > 导致错误

我有三个文件MyType.hMyType.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 - &gt; 工作正常。

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;
}

请让我知道我在 技术1

中所犯的错误

5 个答案:

答案 0 :(得分:3)

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

修改

您必须包含方法实现,因此编译器可以看到它。你可以通过从另一个`MyType_impl.h“文件中包含它们来实现它:

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

答案 1 :(得分:2)

技术1对于模板是错误的。不要使用它。

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

答案 2 :(得分: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 / header

答案 3 :(得分:1)

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

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

这可以帮助您避免编译错误。

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

答案 4 :(得分:1)

第一个版本有两个问题。

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

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

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