编译器说每个构造函数和函数都被重新定义并且不会编译。我用错 #IFNDEF 了吗?-C++

Compiler says every constructor and function is being redefined and won't compile. Am I using the #IFNDEF wrong? - C++

本文关键字:编译 -C++ 了吗 #IFNDEF 定义 构造函数 函数 新定义 编译器      更新时间:2023-10-16

我正在尝试使用类模板实现我自己的 OrderedList 数据结构。我的 CPP 文件中的每个构造函数和函数在开头的"{"上都有一个错误。该错误显示为"重新定义先前在此处声明FUNCTION_NAME FUNTION_NAME"。

我让一些同事看过它,但无济于事。这是我的文件和错误:

CPP 文件 "MyOrderedList.cpp"

#include "MyOrderedList.h"
template <class E>
MyOrderedList<E>::MyOrderedList() {/*IMPLEMENTATION*/}
template <class E>
MyOrderedList<E>::MyOrderedList(const MyOrderedList<E>& orig) { /*IMPLEMENTATION*/}
template <class E>
void MyOrderedList<E>::operator =(const MyOrderedList<E>& orig){/*IMPLEMENTATION*/}
template <class E>
MyOrderedList<E>::~MyOrderedList() {/*IMPLEMENTATION*/}
template <class E>
void MyOrderedList<E>::insert(E data){/*IMPLEMENTATION*/}
template <class E>
E MyOrderedList<E>::get(int pos) const{/*IMPLEMENTATION*/}
template <class E>
Node<E>* MyOrderedList<E>::getHead() const{/*IMPLEMENTATION*/}
template <class E>
MyOrderedList<E> MyOrderedList<E>::kLargest(int k) const{/*IMPLEMENTATION*/}
template <class E>
MyOrderedList<E> MyOrderedList<E>::operator +(const MyOrderedList<E>& list {/*IMPLEMENTATION*/}

H FILE "MyOrderedList.h"

#ifndef MYORDEREDLIST_H
#define MYORDEREDLIST_H
#include <iostream>
#include <cstdlib>
#include "Node.h"
template <class E>
class MyOrderedList;
template <class E>
std::ostream& operator <<(std::ostream& out, const MyOrderedList<E>& list);
template <class E>
class MyOrderedList {
public:
    MyOrderedList();
    MyOrderedList(const MyOrderedList<E>& orig);
    void operator =(const MyOrderedList<E>& orig);
    virtual ~MyOrderedList();
    bool remove(E data);
    MyOrderedList<E> kLargest(int k) const;
    E get(int pos) const;
    void insert(E data);
    Node<E>* getHead() const;
    MyOrderedList<E> operator +(const MyOrderedList<E>& list);
    friend std::ostream& operator <<(std::ostream& out, const MyOrderedList<E>& list){/*IMPLEMENTATION*/}
private:
    Node<E>* head;
    int size;
};
#include "MyOrderedList.cpp"
#endif  //MYORDEREDLIST_H

节点.h

#ifndef NODE_H
#define NODE_H
#include <iostream>
template <class E>
class Node {
public:
    Node(const E& init_data = NULL, Node<E>* init_link = NULL){data = init_data; link = init_link;}
    Node(const Node<E>& orig);
    virtual ~Node();
    E getData() const{return data;}
    void setData(E newData);
    Node<E>* getLink(){return link;}
    void setLink(Node<E>* nextLink) {link = nextLink;}
private:
    E data;
    Node<E>* link;
};
#endif  /* NODE_H */

编译器错误

MyOrderedList.cpp:12: error: redefinition of `MyOrderedList<E>::MyOrderedList()'
MyOrderedList.cpp:12: error: `MyOrderedList<E>::MyOrderedList()' previously declared here
MyOrderedList.cpp:19: error: redefinition of `MyOrderedList<E>::MyOrderedList(const MyOrderedList<E>&)'
MyOrderedList.cpp:19: error: `MyOrderedList<E>::MyOrderedList(const MyOrderedList<E>&)' previously declared here
MyOrderedList.cpp:42: error: redefinition of `void MyOrderedList<E>::operator=(const MyOrderedList<E>&)'
MyOrderedList.cpp:42: error: `void MyOrderedList<E>::operator=(const MyOrderedList<E>&)' previously declared here
MyOrderedList.cpp:77: error: redefinition of `MyOrderedList<E>::~MyOrderedList()'
MyOrderedList.cpp:77: error: `virtual MyOrderedList<E>::~MyOrderedList()' previously declared here
MyOrderedList.cpp:91: error: redefinition of `void MyOrderedList<E>::insert(E)'
MyOrderedList.cpp:91: error: `void MyOrderedList<E>::insert(E)' previously declared here
MyOrderedList.cpp:119: error: redefinition of `E MyOrderedList<E>::get(int) const'
MyOrderedList.cpp:119: error: `E MyOrderedList<E>::get(int) const' previously declared here
MyOrderedList.cpp:134: error: redefinition of `Node<E>* MyOrderedList<E>::getHead() const'
MyOrderedList.cpp:134: error: `Node<E>* MyOrderedList<E>::getHead() const' previously declared here
MyOrderedList.cpp:140: error: redefinition of `MyOrderedList<E> MyOrderedList<E>::kLargest(int) const'
MyOrderedList.cpp:140: error: `MyOrderedList<E> MyOrderedList<E>::kLargest(int) const' previously declared here
MyOrderedList.cpp:158: error: redefinition of `MyOrderedList<E> MyOrderedList<E>::operator+(const MyOrderedList<E>&)'
MyOrderedList.cpp:158: error: `MyOrderedList<E> MyOrderedList<E>::operator+(const MyOrderedList<E>&)' previously declared here

您的问题是您在标头中包含函数的定义(间接通过#include "MyOrderedList.cpp" .由于函数未声明为 inline因此编译器将在包含标头的所有翻译单元中生成符号,因此您将获得多重定义的符号。

该问题的一种解决方案是将函数声明为定义中的inline函数,以便链接器可以丢弃重复项。将定义保存在单独的文件中并不是什么新鲜事,但也不是太常见,一些标准库实现就是这样做的。但是考虑将.cpp重命名为其他名称以避免混淆(大多数人会认为.cpp意味着它应该被编译,而不是包含在内)。

另一方面,我建议进一步简化它,完全删除.cpp,只拥有所有内容的 .h(仍然将所有函数定义标记为 inline ),甚至更进一步并定义类定义中的函数,默认情况下它们是inline的。

您的.cpp.h文件相互#include。 为什么?

模板类的声明和定义需要保持在一起。 为了做到这一点,在.cpp文件上使用#include并没有错,但是您的.cpp文件也需要标头保护(即 #ifndef MYORDEREDLIST_CPP等)。然而,通常的方法是将所有内容都推入同一个.h文件中

注意 - 模板类/函数是您需要#include.cpp文件或将定义放入头文件中的唯一时间。