从.h在.cpp中定义模板化函数(出现错误)

Defining templated functions in .cpp from .h (getting error)

本文关键字:函数 错误 cpp 定义      更新时间:2023-10-16

头文件dlist.h的一部分定义为:

#ifndef __DLIST_H__
#define __DLIST_H__
#include <iostream>
class emptyList {};
template <typename T>
class Dlist {
public:
bool isEmpty() const;
private:
struct node {
node   *next;
node   *prev;
T      *o;
};
node   *first; // The pointer to the first node (NULL if none)
node   *last;  // The pointer to the last node (NULL if none)
};
#include "dlist.cpp"
#endif

当我创建这样的dlist.cpp文件时:

#include "dlist.h"
template <typename T>
bool Dlist<T>::isEmpty() const
{
return !first and !last;
}

我在第4行收到错误消息:"bool Dlist::isEmpty()const"的重新定义

如果我删除#include "dlist.h",我会在第4行得到错误:"<"之前应为初始值设定项代币

这里有人帮忙吗?是不是我做错了什么,不允许我从dlist.h文件中定义函数?非常感谢。

您必须将类模板的成员函数的实现放在头文件中,或者放在头所包含的文件中。编译器需要访问此代码,以便实例化任何给定类型T的模板。

在您的情况下,问题似乎是您在.cpp中包含了标头,反之亦然。如果您真的想将声明和实现保存在单独的文件中,我建议将实现的后缀从.cpp更改为其他内容,例如.icpp。一些构建系统可能会尝试用任何带有.cpp后缀的东西编译对象文件,这也会导致错误。

  1. dlist.cpp中删除#include "dlist.h"
  2. (可选)将dlist.cpp重命名为类似dlist.icpp的名称。为什么?因为许多构建系统会自动将任何以.cpp结尾的文件编译为对象文件。许多程序员认为.cpp文件编译为对象文件
  3. (仅当采取步骤2时)将重新命名的dlist.icpp包括在dlist.h中,就像当前对dlis.cpp所做的那样

头文件是为我定义的,我不允许以任何方式更改

然后,您需要从.cpp中删除#include "dlist.h"指令(因为您已经在dlist.h了,因此创建了一个循环依赖项),从而使所有内容都完全向后,因为给您的标头太愚蠢了!

.cpp不应#included。通常,如果必须将与模板相关的定义拆分到自己的文件中,则它应该具有其他扩展名。我强烈建议你与授权你的人交谈,并解释他们的标题是愚蠢的、令人困惑的和非传统的。

不要在头文件中使用#include "dlist.cpp",而是将函数定义移动到dlist.h中。

为什么在.h文件中包含.cpp文件?99%的情况下你不应该那样做。

只需添加您的代码

template <typename T>
bool Dlist<T>::isEmpty() const
{
return !first and !last;
}

而不是.cpp文件include指令。

删除#include "dlist.h",不要编译dlist.cpp本身。

你也可以使用这样的东西:

因为dlist.h包括dlist.cpp并定义了__DLIST_H__:

#define __DLIST_H__

您可以将dlist.cpp修改为

#ifdef __DLIST_H__
template <typename T>
bool Dlist<T>::isEmpty() const
{
return !first and !last;
}
#endif

这样,如果你试图编译dlist.cpp,就不会出现编译器错误。但我同意其他答案,最好不要将此文件命名为.cpp.