从.h中定义.cpp中的模板化函数(获取错误)

时间:2012-12-01 10:47:08

标签: c++

头文件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行得到错误:在'&lt;'之前的预期初始值设定项令牌

这里有什么帮助吗?有什么我做错了,不允许我从dlist.h文件中定义我的函数吗?谢谢。

5 个答案:

答案 0 :(得分:7)

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

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

  1. #include "dlist.h"移除dlist.cpp
  2. (可选)将dlist.cpp重命名为dlist.icpp。为什么?因为许多构建系统会自动将以.cpp结尾的任何文件编译到目标文件中。许多程序员都认为.cpp文件编译成目标文件。
  3. (仅当采取第2步时)在dlist.icpp中包含重新命名的dlist.h,与dlis.cpp目前相同。

答案 1 :(得分:2)

  

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

然后,您需要从#include "dlist.h"中移除.cpp指令(因为您已经 dlist.h中的,从而创建了循环依赖),因此把所有东西都完全倒退了,因为给你的标题是愚蠢的!

.cpp 永远不会成为#included。通常,如果一个必须将与模板相关的定义拆分到它们自己的文件中,它应该有一些其他扩展名。我强烈建议你和那个掌管这个任务的人谈谈,并解释他们的标题是愚蠢的,混乱的和非传统的。

答案 2 :(得分:1)

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

答案 3 :(得分:1)

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

只需添加您的代码

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

而不是.cpp文件包含指令。

答案 4 :(得分:0)

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

您还可以使用this

之类的内容

因为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。