C ++中未定义的引用错误

时间:2010-05-23 07:08:32

标签: c++ include linker header-files

我有Record.h和Record.cpp文件。当我只包含Record.h文件时,我会在这些文件中定义的函数中获得几个未定义的引用错误。当我还包括Record.cpp时,错误就会消失。这是为什么? Record.h具有函数的前向声明,它声称是未定义的引用。

Record.h

#ifndef RECORD_
#define RECORD_

#include <string>
#include <limits>
using namespace std;

#define PKEYSIZE 10
#define STREETNUMSIZE 8
#define STREETNAMESIZE 24
#define RNAMESIZE 30
#define ASTYLESIZE 20
#define YEARSIZE 12

#define MAXBUCKETSIZE 4
#define MAXDIRECTORYSIZE 100

typedef struct
{

        char streetNum[STREETNUMSIZE];
        char streetName[STREETNAMESIZE];
        char rName[RNAMESIZE];
        char aStyle[ASTYLESIZE];
        char year[YEARSIZE];
        char pkey[PKEYSIZE];

} RECORD;

typedef struct
{
    int size;
    int depth;
    RECORD record[MAXBUCKETSIZE];

} BUCKET;


#define HEADERSIZE 2L

#define NODESIZE sizeof(BUCKET)

void addKey(RECORD *rec_ptr, string key);
void addStreetNum(RECORD *rec_ptr, string s);
void addStreetName(RECORD *rec_ptr, string s);
void addRName(RECORD *rec_ptr, string s);
void addAStyle(RECORD *rec_ptr, string s);
void addYear(RECORD *rec_ptr, string s);
void printRecord(RECORD *rec_ptr);
ostream & operator<<(ostream & out, RECORD *r);

string cvt_binary(unsigned int input);
void addRecord(RECORD *r);
void showbucket(int n);

#endif

Record.cpp

int dirDepth = 0;
int numberOfBuckets = 0;
int directory[MAXDIRECTORYSIZE];
BUCKET bucket[MAXDIRECTORYSIZE/MAXBUCKETSIZE];

void addKey(RECORD *rec_ptr, string key)
{
    strncpy(rec_ptr->pkey, key.c_str(), PKEYSIZE);

}

void addStreetNum(RECORD *rec_ptr, string s)
{
    strncpy(rec_ptr->streetNum, s.c_str(), STREETNUMSIZE);
}

void addStreetName(RECORD *rec_ptr, string s)
{
    strncpy(rec_ptr->streetName, s.c_str(), STREETNAMESIZE);
}

void addRName(RECORD *rec_ptr, string s)
{
    strncpy(rec_ptr->rName, s.c_str(), RNAMESIZE);
}

void addAStyle(RECORD *rec_ptr, string s)
{
    strncpy(rec_ptr->aStyle, s.c_str(), ASTYLESIZE);
}


void addYear(RECORD *rec_ptr, string s)
{
    strncpy(rec_ptr->year, s.c_str(), YEARSIZE);
}

void printRecord(RECORD *rec_ptr)
{

    cout<< "|"
        << rec_ptr->pkey << "|" 
        << rec_ptr->streetNum << "|" 
        << rec_ptr->streetName << "|" 
        << rec_ptr->rName << "|" 
        << rec_ptr->aStyle << "|" 
        << rec_ptr->year << endl;

}


ostream & operator<<(ostream & out, RECORD *r)
{
    out << r->pkey << r->streetNum << r->streetName << r->rName
        << r->aStyle << r->year << endl;
    return out;

}

int bucketread(short rrn, BUCKET *page_ptr)
{
//  long lseek(), addr;
    long addr;

    addr = (long)rrn * (long)NODESIZE + HEADERSIZE;
    lseek(btfd, addr, 0);
    return ( read(btfd, page_ptr, NODESIZE) );
}

int bucketwrite(short rrn, BUCKET *page_ptr)
{
//    long lseek(), addr;
    long addr;
    addr = (long) rrn * (long) NODESIZE + HEADERSIZE;
    lseek(btfd, addr, 0);
    return (write(btfd, page_ptr, NODESIZE));
}

void showbucket(int n)
{
    cout << "loading bucket " << n << endl;
    BUCKET b;
    bucketread(n, &b);
    cout << "there are " << b.size << " records in the bucket" << endl;

}

string cvt_binary(unsigned int input) {
    if(input == 0) return "0"; // trivial case
    string result;
    for(int i = numeric_limits<unsigned int>::digits - 1; i >= 0; --i) {
        if(input & (1 << i)) 
        {
            result += "1";
        } 
        else 
        {
            if(!result.empty()) result += "0";
        }
    }
    return result;
}


string hash (char* key)
{
    int sum = 0;
    int len = strlen(key);
    if (len % 2 == 1) len++; // make len even
    //for an odd length string, use the trailing 0 as part of key
    for (int j = 0; j < len; j +=2)
        sum = (sum + 100 * key[j] + key[j+1]) % 19937;
    return cvt_binary(sum);
}

void copyrecord(RECORD *dest, RECORD *src)
{
    cout << "copying record" << endl;
    addKey(dest, src->pkey);
    addStreetNum(dest, src->streetNum);
    addStreetName(dest, src->streetName);
    addRName(dest, src->rName);
    addAStyle(dest, src->aStyle);
    addYear(dest, src->year);
}

void addToBucket(int n, RECORD *r)
{
    cout << "Adding record " << r->pkey << " to bucket " << n << endl;
    if (bucket[n].size == MAXBUCKETSIZE)
    {
        cout << "Bucket " << n << " is full." << endl;
        // examine bucket depth and directory depth to determine next action
        cout << "Bucket depth: " << bucket[n].depth << endl;
        cout << "Directory depth: " << directory[0] << endl;
    }
    else
    {
        copyrecord(&bucket[n].record[bucket[n].size],r);
        bucket[n].size++;
        bucketwrite(1,&bucket[1]);


    }

}

string getreverse(string key, int num)
{
    if(num==0)
        return "";
    string newstring;
    newstring = key.at(key.length());
    newstring+= getreverse(key.substr(0,key.length()-1),num-1);

    return newstring;
}

void addRecord(RECORD *r)
{
    cout << r->pkey << endl;
    string hashvalue = hash(r->pkey);
    cout << "hash value is " << hashvalue << endl;

    int directoryDepth = directory[0];

    if(directoryDepth == 0)
    {
        directory[1] = 1;
        addToBucket(1, r);
    }
    else
    {
        // use hashing to figure out which bucket to add to
        cout << "The relevant string is" <<  getreverse(hashvalue, directoryDepth) << endl;

    }

}

3 个答案:

答案 0 :(得分:3)

Record.h具有这些功能的声明。 Record.cpp具有定义

//Record.h

void foo(); // This is a forward declaration

到目前为止一切顺利。

//main.cpp

#include "Record.h"

int main()
{
    foo();
}

现在main.o会编译得很好。但是,如果您尝试将其链接到工作二进制文件,则会收到void foo()未定义的投诉。

//Record.cpp

#include "Record.h"

// This is the definition
void foo()
{
    // do various things
}

这可以编译成Record.o,然后可以将其与main.o链接到工作的可执行文件中。

答案 1 :(得分:3)

通过包含标题提供 声明 编译器所需要的。 链接器需要 定义 。它会在编译器编译源文件时在编译器创建的目标文件中找到它们 我没有使用gcc,但我认为可以使用所有源文件调用它,然后使用提供的所有目标文件调用链接器:g++ main.cpp record.cpp

答案 2 :(得分:0)

我的C ++可能有点生疏,但听起来Record.cpp没有被编译到解决方案中。如果.cpp文件不存在,则标题中没有引用。不要包含cpp,但要检查链接器设置,或者用于编译程序的命令......它需要包含所有cpps。