【问题标题】:Define template in header file and definition in a cpp file within derived class [duplicate]在派生类的头文件中定义模板并在cpp文件中定义[重复]
【发布时间】:2012-10-18 17:59:10
【问题描述】:

可能重复:
Why should the implementation and the declaration of a template class be in the same header file?

我正在尝试在头文件中定义模板,并在 cpp 文件中定义模板,并且模板应在派生类中定义。所以这就是我得到的:

头文件:

#ifndef  ........
#define .....
 template <class mytypename>
 class abcBaseClass:public abcDerivedClass{
 public:
     mytypename getvalue(char*)
};
#endif


源文件:

mytypename abcDerivedClass<mytypename>::getvalue(char* name){

}

我只是想知道这样做是否正确?

这就是我想要实现的目标......我想要拨打电话的最后一种方式是

double x = a->getvalue<double>(char)

【问题讨论】:

  • 除非您显式实例化类型,否则实现必须与声明位于同一文件中。 typename 也是保留字。
  • 正确的做法是将整个模板定义放在表头中。
  • 你真正想做什么? typename 不是模板参数的有效名称,并且在该代码中,base 继承自 derived,这至少是一个违反直觉的名称选择。
  • Mybad...忽略类型名...感谢大家通知我...我刚刚将其更改为 mytypename...除此之外...我只是想知道是否我是对的......我只是希望我的模板定义和声明位于单独的文件中
  • @vadugs,阅读我的解决方法(有一些缺陷)的答案。此外,Mark 的回答提供了另一种解决方法,不过需要一些额外的工作。

标签: c++


【解决方案1】:

类似的问题已经在 SO 上被问过很多次了。

但无论如何...

首先,你犯了一些语法错误。

代替

#ifndef  ........
#define .....
 template <class typename>
 class abcBaseClass:public abcDerivedClass{
 public:
     typename getvalue(char*);
};
#endif

应该是这样的。

#ifndef  ........
#define .....
 template <typename T>
 class abcBaseClass:public abcDerivedClass{
 public:
     T getvalue(char*);
};
// Definition follow in this file!
// For reasons or work-arounds, read below.
#endif

此外,模板声明和定义都应该放在同一个文件中。 一个例外是当您将该模板实例化为模板定义所在的源文件中的某种类型时。

类似的东西。

#include "this_template.h"

template <typename T>
// all sorts of definitions...

// Explicit instantiate this template!!!!
template class abcBaseClass<Your_Type_Goes_Here>;

注意,这种方法的一个根本缺陷是,您只能在程序的其他任何地方使用您在此源文件中显式实例化的类型。尝试使用其他类型实例化此模板将导致链接器抱怨找不到匹配的定义。

如果您坚持模板是通用的并且在其他地方定义模板类。 您可以将定义放入另一个头文件中,只需将其命名为this_template_impl.h 并将this_template.h 包含在this_template_impl.h

然后,在你的源文件中,你写的是#include "this_template_impl.h,而不是#include "this_template.h"

【讨论】:

  • 嘿,非常感谢。我现在正试图在一个文件中完成它,我希望如何完成定义......这适合你所说的格式吗? abcDerivedClass::getvalue(char* name)
【解决方案2】:

您可以将定义放在 .cpp 文件中,但这比较麻烦,而且不是模板通常的做法。

您需要在 .cpp 中添加一些额外的代码来说服编译器生成填充了必要模板参数的函数。一种方法是以某种方式使用该函数:

mytypename abcDerivedClass<mytypename>::getvalue(char* name){

}

void dummy()
{
    abcDerivedClass<double> temp;
    temp->getvalue(NULL);
}

不需要实际调用虚拟函数,只需将它放在那里(在模板定义之后)就足够了。

我确信还有另一种显式实例化模板的方法,但由于我不这样做,所以我永远记不得了。

【讨论】:

  • 只是template mytypename abcDerivedClass&lt;double&gt;::getvalue(char*);
【解决方案3】:

不,这不是正确的方法:

应该这样做:

#ifndef  ........
#define .....
 template <class T>
 class abcBaseClass:public abcDerivedClass{
 public:
     T getvalue(char*)
};

#endif

在 .cpp 文件中: 模板 T abcBaseClass::getvalue(char * ch){ }

您的代码不正确的原因是 typename 是 C++ 关键字。并且必须在编译过程中抛出错误

你也可以使用:

#ifndef  ........
#define .....
 template <typename T>
 class abcBaseClass:public abcDerivedClass{
 public:
     T getvalue(char*)
};
#endif

在 C++ 文件中:

template<class T>
T abcBaseClass<T>::getvalue(char * ch){
}

【讨论】:

  • 好吧,你不能像 C++ 中的其他东西那样将模板的定义真正放入 .cpp 文件中。有一种变通方法,但它仍然不同于您通常分隔头文件/源文件的方式
猜你喜欢
  • 2015-09-15
  • 2022-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多