[英]undefined reference errors in C++
I have files Record.h and Record.cpp. 我有Record.h和Record.cpp文件。 When I just include the Record.h file, I get several undefined reference errors to functions defined in those files. 当我仅包含Record.h文件时,对于这些文件中定义的函数,我得到了几个未定义的引用错误。 When I also include Record.cpp then the errors go away. 当我还包含Record.cpp时,错误就会消失。 Why is that? 这是为什么? Record.h has the forward declarations for the functions it says are an undefined reference. Record.h具有其未定义引用的函数的前向声明。
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 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;
}
}
Record.h has the declarations of those functions. Record.h具有这些函数的声明 。 Record.cpp has the definitions . Record.cpp具有定义 。
//Record.h
void foo(); // This is a forward declaration
So far so good. 到现在为止还挺好。
//main.cpp
#include "Record.h"
int main()
{
foo();
}
Now main.o will compile just fine. 现在main.o将可以正常编译。 But if you try to link it into a working binary, you'll get a complaint that void foo()
is undefined. 但是,如果尝试将其链接到有效的二进制文件中,则会抱怨void foo()
未定义。
//Record.cpp
#include "Record.h"
// This is the definition
void foo()
{
// do various things
}
This can be compiled into Record.o, which can then be linked with main.o into a working executable. 可以将其编译到Record.o中,然后可以将它与main.o链接到工作的可执行文件中。
Providing the declarations by including the header is what the compiler needs. 通过包括标头来提供声明是编译器需要的。 The linker needs the definitions . 链接器需要定义 。 It will find these in the object files the compiler creates when it compiles source files. 它将在编译器编译源文件时创建的目标文件中找到这些文件。
I'm not using gcc, but I think it can just be called with all the source files and will then call the linker with all the object files provided: g++ main.cpp record.cpp
. 我没有使用gcc,但是我认为可以使用所有源文件调用它,然后使用提供的所有目标文件调用链接器: g++ main.cpp record.cpp
。
My C++ might be a bit rusty, but it sounds like Record.cpp
isn't being compiled into the solution. 我的C ++可能有点生锈,但是听起来Record.cpp
没有被编译到解决方案中。 If the .cpp
file isn't there, then the header has nothing to refer to. 如果.cpp
文件不存在,则标题无可参考 。 Don't include the cpp, but check your linker settings, or the command you're using to compile your program... it needs to include all the cpps. 不包括cpp,但是请检查您的链接器设置或用于编译程序的命令...它需要包括所有cpp。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.