对(函数)C++ 的未定义引用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12772103/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 16:36:20  来源:igfitidea点击:

undefined reference to (function) c++

c++functionreferenceheaderundefined

提问by JoshH

Possible Duplicate:
Undefined Reference to

可能的重复:
未定义的引用

I've been banging my head against this one set of error messages for about 4 hours now and I can't seem to figure it out. I've not posted here before, so I apologize in advance if it's not in the right area or I've done something wrong. At any rate, the error messages I'm receiving are:

大约 4 个小时以来,我一直对这组错误消息感到头疼,但我似乎无法弄清楚。我以前没有在这里发布过,所以如果它不在正确的区域或我做错了什么,我提前道歉。无论如何,我收到的错误消息是:

main.cpp|28|undefined reference to `LinkedSortedList<Employee>::LinkedSortedList()'|
   main.cpp|52|undefined reference to `empPrint(LinkedSortedList<Employee>&)'|
   main.cpp|58|undefined reference to `empSave(LinkedSortedList<Employee>&, std::string)'|
   main.cpp|65|undefined reference to `empLoad(LinkedSortedList<Employee>&, std::string)'|
   main.cpp|70|undefined reference to `LinkedSortedList<Employee>::~LinkedSortedList()'|
   main.cpp|70|undefined reference to `LinkedSortedList<Employee>::~LinkedSortedList()'|

   obj\Debug\main.o||In function `Z9empSearchR16LinkedSortedListI8EmployeeE':|
   main.cpp|109|undefined reference to `LinkedSortedList<Employee>::getHead()'|

My main.cpp is as follows:

我的 main.cpp 如下:

#include <iostream>
#include <string>
#include <stdio.h>
#include <fstream>
#include "SortedList.h"
#include "LinkedSortedList.h"
#include "Employee.h"
#include "LinkedNode.h"

using namespace std;

void newEmp(LinkedSortedList <Employee>& empList);
void empSearch(LinkedSortedList <Employee>& empList);
void empPrint(LinkedSortedList <Employee>& empList);
void empSave(LinkedSortedList <Employee>& empList, string file);
void empLoad(LinkedSortedList <Employee>& empList, string file);

int main()
{
    //int empID;
    bool menuFinish = false;
    LinkedSortedList<Employee> empList;
    char selection;

    while (!menuFinish)

        //simple menu system through cout, the selection is read in through cin
        //and converted to upper case for simplicity during the conditionals
        cout << "Menu" << endl;
        cout << "(I)nsert new record" << endl;
        cout << "(E)mployee ID search" << endl;
        cout << "(P)rint employee info" << endl;
        cout << "(S)ave database to a file" << endl;
        cout << "(L)oad database from file" << endl;
        cout << "(Q)uit" << endl;
        cout << "Enter selection " << endl;
        cin >> selection;
        selection = toupper(selection);

        //menu selections are compared with their functions
        if (selection == 'I')
            newEmp(empList);
        else if (selection == 'E')
            empSearch(empList);
        else if (selection == 'P')
            empPrint(empList);
        else if (selection == 'S')
            {
                string fileName;
                cout << "Enter a filename to save the database to " << endl;
                cin >> fileName;
                empSave(empList, fileName);
            }
        else if (selection == 'L')
            {
                string fileName;
                cout << "Enter the filename to load the database from " << endl;
                cin >> fileName;
                empLoad(empList, fileName);
            }
        else if (selection == 'Q')
            menuFinish = true;
        else
            cout << "Incorrect choice " << endl;
}

//function creates a new employee
void newEmp(LinkedSortedList <Employee>& empList)
{
    string firstName;
    string lastName;
    int empID = -1;

    cout << "Please enter the first name " << endl;
    cin >> firstName;
    cout << "Please enter the last name " << endl;
    cin >> lastName;
    while (empID > 9999999 || empID < 0)
        {
        cout <<"Please enter the employee ID " << endl;
        cin >> empID;

        }
    //puts the employee in the db unless they're already found, then outputs an
    //error on the screen
    Employee emp(firstName, lastName, empID);
    bool findEmp = empList.find(emp);

    if (!findEmp)
        empList.insert(emp);
    else
        cout << "Emlpoyee ID " << empID << " already in use " << endl;
}

//function to search for an employee based on their employee ID
void empSearch (LinkedSortedList <Employee>& empList)
{
    int empID;
    int sizeOfList = 0;
    bool noEmp = true;

    cout << "Enter employee ID " << endl;
    cin >> empID;

    LinkedNode <Employee>* temp = empList.getHead();
    while (sizeOfList < empList.size() && noEmp)
    {
        sizeOfList++;
        if (empID == temp->value.getEmpID())
            {
                cout << "Searched " << sizeOfList << "employees " << endl;
                cout << "Found record: " << temp->value;
                noEmp = false;
            }
            temp = temp->next;
    }
    if (noEmp)
    cout << "Search of " << sizeOfList << " employees.  Employee not found" << endl;

}

//function used to print the first and last five employees from the db
void empPrint (LinkedSortedList <Employee>& empList)
{
    if (empList.size() <= 10)
        {
            empList.print();
        }

        else
        {
            LinkedNode<Employee>* temp = empList.getHead();
            cout << "First five employees: " << endl;

            for (int i = 0; i < 5; i++)
                {
                cout << temp->value << endl;
                i++;
                temp = temp->next;
                }

            int midList = empList.size()-5;
            for (int i = 0; i < midList; i++)
                {
                     temp = temp->next;
                }

            cout << "Last five employees: " << endl;
            for (int i = 0; i < 5; i++)
                {
                    cout << temp->value << endl;
                    i++;
                    temp = temp->next;
                }
        }
}

//function used to save the employee information from the db to a file
void empSave(LinkedSortedList<Employee>& empList, string fileName)
{
    string lastName;
    string firstName;
    //int empID;
    ofstream output;
    output.open(fileName.c_str());
    if (!output)
        {
            cout << "File not saved" << endl;
        }
    else
    {
        LinkedNode<Employee>* temp = empList.getHead();
        int i = 0;
        while (i < empList.size())
        {
            output << temp->value.getLastName() << " " << temp->value.getFirstName() << " " << temp->value.getEmpID() << endl;
            i++;
            temp = temp->next;
        }
    }
    output.close();
}

//function used to load the employee information from a file to the db
void empLoad(LinkedSortedList<Employee>& empList, string fileName)
{
    if (empList.size() > 0)
    {
        empList.clear();
    }

    ifstream input;
    input.open(fileName.c_str());

    if (!input)
    {
        cout << "No file exists" << endl;
    }

    else
    {
        int empID;
        string firstName;
        string lastName;
        string delimiter;

        while(input.good());
        {
            getline(input, delimiter, '\n');
            getline(input, lastName, ' ');
            getline(input, firstName, ' ');
            input >> empID;

            Employee emp(lastName, firstName, empID);

            bool empFound = empList.find(emp);

            if(!empFound)
            {
                empList.insert(emp);
            }
            else
            cout << "Employee already exists" << endl;
        }
    }
}

My LinkedSortList.cpp is:

我的 LinkedSortList.cpp 是:

#ifndef _LinkedSortedList_
#define _LinkedSortedList_

#include "Employee.h"
#include "LinkedSortedList.h"
#include "SortedList.h"
#include "LinkedNode.h"

#include <iostream>
#include <fstream>
#include <string>


using namespace std;

//default constructor
//sets head to null and makes the size of the list 0
template <class Elem>
LinkedSortedList<Elem>::LinkedSortedList()
{
    head = NULL;
    listSize = 0;
}

//destructor, clears list THEN deletes the head so memory leaks are
//stopped
template <class Elem>
LinkedSortedList<Elem>::~LinkedSortedList()
{
    clear();
    delete head;
}

//clears the list, freeing memory and stopping leaks and resets the
//list size
template <class Elem>
void LinkedSortedList<Elem>::clear()
{
    LinkedNode<Elem> *indexPtr = head;

    while (head != NULL)
    {
        head = head->next;
        delete indexPtr;
        indexPtr = head;
    }
    listSize = 0;
}

//finds a search value in the list... if it finds it then it returns true,
//otherwise it returns false
template <class Elem>
bool LinkedSortedList<Elem>::find(Elem searchValue) const
{
    LinkedNode<Elem>* indexPtr = head;
    while (indexPtr != NULL)
    {
        if (indexPtr->value == searchValue)
        {
            return true;
        }
        indexPtr = indexPtr->next;


    }
    return false;
}

//gets and DELETES first value in the list - if it finds nothing then
//return false, otherwise true
template <class Elem>
bool LinkedSortedList<Elem>::getFirst(Elem &returnValue)
{
    LinkedNode<Elem>* indexPtr = head;
    if (indexPtr == NULL)
        return false;
        else
        {
            head = head->next;
            returnValue = indexPtr->value;
            delete indexPtr;
            listSize--;
            return true;
        }
        returnValue = indexPtr->value;
}

//prints the list to cout or prints a warning if the list contains
//no values
template <class Elem>
void LinkedSortedList<Elem>::print() const
{

    if (head == NULL)
    {
         cout << "No elements in the list" << endl;
    }
        else
        {
            LinkedNode<Elem>* indexPtr = head;
            while (indexPtr != NULL)
            {
                cout << indexPtr->value << endl;
                indexPtr = indexPtr->next;
            }
        }
}

//returns the size of the list to the caller
template <class Elem>
int LinkedSortedList<Elem>::size() const
{
    return listSize;
}

//inserts a value into the list where it should go, if the list is empty it will
//say there are no existing nodes
template <class Elem>
bool LinkedSortedList<Elem>::insert(Elem newValue)
{
    LinkedNode<Elem>* indexPtr = head;
    LinkedNode<Elem>* newNode;
    //newNode->value = newValue;

     try
    {
        newNode = new LinkedNode<Elem>(newValue);
    }
    catch(exception e)
    {
        cout<<"Exception reached: " << e.what() << endl;
        return false;
    }

    //checks to see if the list is empty, if it is then it makes the newNode
    //the head
    if (head == NULL)
        {
            cout << "No existing nodes" << endl;
            head = newNode;
            cout << "First node is now " << head->value << endl;
            listSize++;
            return true;
        }

        /*looks to see if the value of the newNode is less than or equal to the
        index, if it is then it sets the point of the newNode equal to the head
        then makes the head the newNode and increments the listSize by one to keep
        track of the size of the list and returns true*/
        else if (newNode->value <= head->value)
        {
            newNode->next = head;
            head = newNode;
            listSize++;
            return true;
        }

        /*if the newNode value is greater than the index, then:*/
        else
        {
            while(indexPtr->next != NULL && newNode->value > indexPtr->next->value)
                {
                    indexPtr = indexPtr->next;
                }

            if (indexPtr->next == NULL)
            {
                indexPtr->next = newNode;
                listSize++;
                return true;
            }
            else
            {
                newNode->next = indexPtr->next;
                indexPtr->next = newNode;
                listSize++;
                return true;
            }

        }
}
//added for project 2 to return the head of the LL
template <class Elem>
LinkedNode<Elem>* LinkedSortedList<Elem>::getHead()
{
    return head;
}


#endif

The Employee.cpp is:

Employee.cpp 是:

#ifndef _Employee_
#define _Employee_

#include "Employee.h"
#include "LinkedSortedList.h"
#include <iostream>
#include <fstream>
#include <string>

using namespace std;

//blank default constructor
Employee::Employee()
{
}

//constructor that takes 3 parameters and sets them
Employee::Employee(string lastName, string firstName, int eID)
{
    this->lastName = lastName;
    this->firstName = firstName;
    this->empID = eID;
}

//blank deconstructor
Employee::~Employee()
{
}

//overloaded equality operator
bool Employee::operator==(Employee &nextEmployee)
{
    if (this->empID == nextEmployee.empID)
            return true;
        else
            return false;
}

//overloaded less than or equal to operator
bool Employee::operator <= (Employee &nextEmployee)
{
    if (this->empID <= nextEmployee.empID)
            return true;
        else
            return false;
}

//overloaded greater than or equal to operator
bool Employee::operator >= (Employee &nextEmployee)
{
    if (this->empID >= nextEmployee.empID)
            return true;
        else
            return false;
}

//overloaded less than operator
bool Employee::operator < (Employee &nextEmployee)
{
    if (this->empID < nextEmployee.empID)
            return true;
        else
            return false;
}

//overloaded greater than operator
bool Employee::operator > (Employee &nextEmployee)
{
    if (this->empID > nextEmployee.empID)
            return true;
        else
            return false;
}

// overloaded output stream operator
ostream& operator<<(ostream& os, const Employee empl)
{
    os << "Last: " << empl.lastName << endl;
    os << "First: " << empl.firstName << endl;
    os << "Employee ID: " << empl.empID << endl;
    return os;
}

#endif

My header file, LinkedSortedList.h:

我的头文件 LinkedSortedList.h:

#ifndef _LinkedSortedListClass_
#define _LinkedSortedListClass_

#include "SortedList.h"
#include "LinkedNode.h"

#include <iostream>
#include <fstream>
#include <string>

//using namespace std;

template <class Elem>
class LinkedSortedList : public SortedList< Elem >
{
public:
    LinkedSortedList();
    ~LinkedSortedList();
    virtual void clear();
    virtual bool insert(Elem newValue);
    virtual bool getFirst(Elem &returnValue);
    virtual void print() const;
    virtual bool find(Elem searchValue) const;
    virtual int size() const;
    LinkedNode<Elem>* getHead(); //added for project 2

private:
    LinkedNode<Elem>* head;
    int listSize;
};
#endif

And finally (WHEW!) my Employee.h is here:

最后(哇!)我的 Employee.h 在这里:

#ifndef _EmployeeClass_
#define _EmployeeClass_

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

class Employee
{
    public:
        Employee();
        ~Employee();
        Employee(string, string, int);
        bool operator == (Employee& nextEmployee);
        bool operator <= (Employee &nextEmployee);
        bool operator >= (Employee &nextEmployee);
        bool operator < (Employee &nextEmployee);
        bool operator > (Employee &nextEmployee);
        friend ostream& operator<<(ostream& os, const Employee empl);
        string getLastName(){return lastName;}
        string getFirstName(){return firstName;}
        int getEmpID(){return empID;}
    private:
        string lastName;
        string firstName;
        int empID;
};

#endif

I'm just not seeing the problem here, I've spoken to my TA, the helproom staff and other students. I haven't heard back from the prof yet, but I doubt I'll hear from her this weekend anyway. Thank you VERY much for any insight you can provide. I need some tylenol. -Josh

我只是没有看到这里的问题,我已经和我的助教、帮助室工作人员和其他学生谈过了。我还没有收到教授的回复,但我怀疑这个周末我是否会收到她的回复。非常感谢您提供的任何见解。我需要一些泰诺。-乔希

回答by Code-Apprentice

How are you compiling your code? If you are using an IDE such as Microsoft Visual C++, be sure to create a project and add all of your .cpp files (not your .h files) to it. If you are using the command-line, be sure to include all of your filenames as command-line arguments. If this still doesn't help. Please include a description of the steps you are using to compile the program.

你如何编译你的代码?如果您使用的是 Microsoft Visual C++ 等 IDE,请务必创建一个项目并将所有 .cpp 文件(而不是 .h 文件)添加到其中。如果您使用命令行,请确保将所有文件名作为命令行参数包含在内。如果这仍然没有帮助。请包括您用于编译程序的步骤的描述。

Edit:

编辑:

There are several issues with your code:

您的代码有几个问题:

  1. #ifndef ... #define...include guards are meant for files which will appear in #includedirectives in other files. Typically these are only .hfiles since it is strongly discouraged to #include.cppfiles.

  2. Classes which use templates must all be in one .h file, not separated into a .hand .cppfile. (READ: In case I haven't made this clear enough, your LinkedSortedListclass must ALL be in one .h file.)

  3. Your main.cppfile declares several functions which are not later defined. If you don't want to take the time to implement these functions yet, you need to at least add empty stubs for them.

  4. Be sure to compile and link all of your source files using a project in your IDE or using the correct command-line arguments. This is what I described in my original answer above.

  1. #ifndef ... #define...包含警卫用于将出现#include在其他文件中的指令中的文件。通常这些只是.h文件,因为强烈不鼓励#include.cpp文件。

  2. 使用模板的类必须都在一个 .h 文件中,而不是分成一个.h.cpp文件。(阅读:如果我还没有说清楚,你的LinkedSortedList班级必须全部在一个 .h 文件中。)

  3. 您的main.cpp文件声明了几个稍后未定义的函数。如果您还不想花时间实现这些功能,您至少需要为它们添加空存根。

  4. 请务必使用 IDE 中的项目或使用正确的命令行参数编译和链接所有源文件。这就是我在上面的原始答案中所描述的。

回答by Dietmar Kühl

To get templates instantiated automatically the compiler needs to the see the definition at the point of use. If you don't want to make the template definition visible you need to use explicit instantiation. How to do either of these is frequently answered.

要自动实例化模板,编译器需要在使用时查看定义。如果您不想使模板定义可见,则需要使用显式实例化。经常回答如何做到这些。

BTW, please don't use names reserved for the implementation of the C++ compiler and its standard library as include guards: names starting with an underscore followed by a capital letter are reserved in all contexts for the C++ implementation.

顺便说一句,请不要使用为 C++ 编译器及其标准库的实现保留的名称作为包含保护:以下划线开头的名称后跟大写字母在 C++ 实现的所有上下文中都是保留的。

回答by David Hammen

My LinkedSortList.cpp is ...

我的 LinkedSortList.cpp 是...

That's the source of most of your problems. Doing what you did doesn't make sense. You need to define those inlinein your header file, LinkedSortedList.h. That covers most of your problems the others, where are you defining empPrint(LinkedSortedList<Employee>&)?

这就是你大部分问题的根源。做你所做的没有意义。您需要在头文件 LinkedSortedList.h 中定义这些内联。这涵盖了您的大部分问题,其他问题,您在哪里定义empPrint(LinkedSortedList<Employee>&)

回答by Jonathan Stray

C++ template methods and functions are not turned into machine code until the compiler runs into a call to the function with a specific type. But that means that the code that defines a template method, for example all of LinkedSortedList.cpp, actually does not produce any code at all when the compiler sees it.

C++ 模板方法和函数在编译器遇到对具有特定类型的函数的调用之前不会转换为机器代码。但这意味着定义模板方法的代码,例如所有 LinkedSortedList.cpp,当编译器看到它时,实际上根本不会产生任何代码。

You need to move all of the code from LinkedSortedList.cpp into LinkedSortedList.h (and similarly for the other templated classes) so that the compiler can produce the code for these methods when they are called. For example the compiler will generate the code for LinkedSortedList::LinkedSortedList() when it is called in main.cpp, but only ifit's already seen the definition for this method in a header file.

您需要将 LinkedSortedList.cpp 中的所有代码移动到 LinkedSortedList.h(对于其他模板化类也是如此),以便编译器可以在调用这些方法时为这些方法生成代码。例如,编译器会为LinkedSortedList),当它被称为main.cpp中的代码:: LinkedSortedList(,但只有当它已经看到了一个头文件中这个方法定义。

Your other option is to use 'explicit instantiation' to force particular versions of particular methods to be compiled into object code.

您的另一个选择是使用“显式实例化”来强制将特定方法的特定版本编译为目标代码。

回答by perilbrain

First of all I cant see definition of these three:-

首先,我看不到这三个的定义:-

void empPrint (LinkedSortedList <Employee>& empList);
void empSave (LinkedSortedList <Employee>& empList, string file);
void empLoad (LinkedSortedList <Employee>& empList, string file);

Hope implementing them will reduce the errors.

希望实施它们会减少错误。