3

部分头文件 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 文件中定义我的函数吗?谢谢你。

4

5 回答 5

7

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

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

  1. #include "dlist.h"从中删除dlist.cpp
  2. (可选)重命名dlist.cppdlist.icpp. 为什么?因为许多构建系统会自动将任何以结尾的文件编译.cpp为目标文件。许多程序员假设一个.cpp文件被编译成一个目标文件。
  3. (仅当采取第 2 步时)包括在 中的重命名dlist.icppdlist.h如当前为dlis.cpp.
于 2012-12-01T10:48:55.790 回答
2

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

然后你需要从 中删除#include "dlist.h"指令.cpp(因为你已经 dlist.h,因此创建了一个循环依赖),从而使一切完全倒退,因为你得到的标题是愚蠢的!

A永远.cpp应该。通常,如果必须将与模板相关的定义拆分到他们自己的文件中,它应该有一些其他的扩展名。我强烈建议您与赋予您此任务的人交谈,并解释他们的标题是愚蠢的、令人困惑的和非传统的。#included

于 2012-12-01T10:59:22.343 回答
1

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

于 2012-12-01T10:48:24.123 回答
1

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

只需添加您的代码

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

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

于 2012-12-01T10:51:50.537 回答
0

删除#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。

于 2012-12-01T10:50:54.033 回答