C++ - 初始化指针的静态向量导致未定义的引用
C++ - initializing static vector of pointers causes undefined reference
我正在尝试在我的 CreateReport class 中创建一个名为 load() 的函数,该函数将我的 graduate.dat 文件中的所有记录(数据)复制到我的静态记录指针向量中,称为主要收藏。我创建了一个 Record class,其中包含构成每个 Record 的变量,并且在 createReport.cc
的 load()
函数中,我尝试读取文件中的每一行,创建一个 Record object每行,将其添加到我的向量中,然后打印 primaryCollection 中的所有内容。
问题是每次我尝试使用 primaryCollection 时,我都会收到错误消息:
CreateReport.o: In function `CreateReport::CreateReport()':
CreateReport.cc:(.text+0x43): undefined reference to `CreateReport::primaryCollection'
CreateReport.o: In function `CreateReport::load()':
CreateReport.cc:(.text+0x2ac): undefined reference to `CreateReport::primaryCollection'
CreateReport.cc:(.text+0x31d): undefined reference to `CreateReport::primaryCollection'
CreateReport.cc:(.text+0x32f): undefined reference to `CreateReport::primaryCollection'
我在 createReport.cc 中提到 primaryCollection 的 4 次得到了 4 个未定义的引用。我不确定我是否正确地初始化了 primaryCollection 以及这是否是导致这些未定义引用的原因。我不知道这是否与我的问题有关,但 CreateReport 也是一个抽象 class 并且有一些名为 ReportOne、ReportTwo 等的子classes
primaryCollection 应该是 Record 指针的静态向量,我也不允许将 std::map 用于此任务。
对于此问题的任何帮助,我将不胜感激。我看了这个 post Undefined reference to static variable c++ 但我还是不太明白该怎么做。我不允许创建全局变量,我正在处理 collection 而不是单个变量。
我的graduate.dat文件格式如下,格式为<年省学位>
2000 AB Bachelor's
2005 AB Bachelor's
2005 MB College
每一行基本上代表一条记录。所以这里的第一个记录是 2000 AB Bachelor's
编辑:所以我根据评论对我的代码进行了更改,添加了行 vector CreateReport::primaryCollection;在我的构造函数之上,但它给了我错误:
CreateReport.cc:13:34: error: conflicting declaration ‘std::vector<Record*> CreateReport::primaryCollection’
vector<Record*> CreateReport::primaryCollection;
^~~~~~~~~~~~~~~~~
In file included from CreateReport.cc:5:0:
CreateReport.h:23:33: note: previous declaration as ‘std::vector<Record*>* CreateReport::primaryCollection’
static std::vector<Record*>* primaryCollection; //STL vector of record pointers
^~~~~~~~~~~~~~~~~
CreateReport.cc:13:34: error: declaration of ‘std::vector<Record*>* CreateReport::primaryCollection’ outside of class is not definition [-fpermissive]
vector<Record*> CreateReport::primaryCollection;
有什么解决办法吗?
Record.h
#ifndef RECORD_H
#define RECORD_H
#include <iostream>
#include <string>
class Record{
public:
Record(int = 0, string = "", string = "");
~Record();
private:
int year;
string province;
string degree;
};
#endif
Record.cc
#include <iostream>
#include <string>
using namespace std;
#include "Record.h"
Record::Record(int i1, string s1, string s2) : year(i1), province(s1), degree(s2){}
Record::~Record(){}
CreateReport.h
#ifndef CREATEREPORT_H
#define CREATEREPORT_H
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>
#include <cstdlib>
#include "Record.h"
class CreateReport{
public:
CreateReport();
static void load();
protected:
static vector<Record*> primaryCollection; //STL vector of record pointers
};
#endif
CreateReport.cc
#include <iostream>
using namespace std;
#include <string>
#include "CreateReport.h"
vector<Record*> CreateReport::primaryCollection;
CreateReport::CreateReport(){
}
void CreateReport::load(){
int year;
string province, degree;
ostream_iterator<Record*> outItr(cout);
ifstream infile("graduate.dat", ios::in);
if (!infile) {
cout << "Error: could not open file" << endl;
exit(1);
}
while (infile >> year >> province >> degree) { //as long as were not at end of file
Record* record = new Record(year, province, degree); //create Record object with this data
primaryCollection->push_back(record); //undefined reference
}
cout<<endl<<"List of Records:"<<endl;
copy(primaryCollection->begin(), primaryCollection->end(), outItr); //2 undefined references
}
三大问题:
- 使用
std::vector<*Record>
会造成许多un-necessary困难;
- 对于静态成员向量,需要在class之外进行额外的定义。
std::vector<Record> CreateReport::primaryCollection;
。这将清除未定义的错误消息。
- 使用复制到std::cout 不起作用,它不提供打印记录的方法。建议写个输出重载。
基于这些,我提供了一个版本如下(将所有 headers 混合在一起。)
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
using namespace std;
class Record{
public:
Record(int = 0, string = "", string = "");
~Record()=default;
friend std::ostream& operator<<(std::ostream&, const Record&);
private:
int year;
string province;
string degree;
};
// **** output overload for Record ***********
std::ostream& operator<<(std::ostream& os, const Record& rd)
{
os << "year = " << rd.year << " prov = " << rd.province << " degree = " << rd.degree << std::endl;
return os;
}
// ****** end of output overload **************
Record::Record(int i1, string s1, string s2) : year(i1), province(s1), degree(s2){}
//end of Record.cc
//
class CreateReport{
public:
CreateReport() = default;
void load();
protected:
static vector<Record> primaryCollection;
};
//***************** you need this line ********************
vector<Record> CreateReport::primaryCollection;
//*********************************************************
void CreateReport::load(){
int year;
string province, degree;
ifstream infile("graduate.dat", ios::in);
if (!infile) {
cout << "Error: could not open file" << endl;
exit(1);
}
while (infile >> year >> province >> degree) {
primaryCollection.push_back( Record(year, province, degree) );
}
cout<<endl<<"List of Records:"<<endl;
for (int i = 0; i<primaryCollection.size(); ++i ) std::cout << primaryCollection[i];
}
int main()
{
CreateReport mime;
mime.load();
}
第二个版本将 `Record*` 用于 `std::vector primaryCollection`。
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
using namespace std;
class Record{
public:
Record(int = 0, string = "", string = "");
~Record()=default;
friend std::ostream& operator<<(std::ostream&, const Record&);
private:
int year;
string province;
string degree;
};
// **** output overload for Record ***********
std::ostream& operator<<(std::ostream& os, const Record& rd)
{
os << "year = " << rd.year << " prov = " << rd.province << " degree = " << rd.degree << std::endl;
return os;
}
// ****** end of output overload **************
Record::Record(int i1, string s1, string s2) : year(i1), province(s1), degree(s2){}
//end of Record.cc
//
class CreateReport{
public:
CreateReport() = default;
void load();
protected:
static vector<Record*> primaryCollection; //STL vector of record pointers
};
//***************** you need this line ********************
std::vector<Record*> CreateReport::primaryCollection;
//*********************************************************
void CreateReport::load(){
int year;
string province, degree;
ifstream infile("graduate.dat", ios::in);
if (!infile) {
cout << "Error: could not open file" << endl;
exit(1);
}
while (infile >> year >> province >> degree) {
Record *a = new Record(year, province, degree);
primaryCollection.push_back( a );
}
cout<<endl<<"List of Records:"<<endl;
for (int i = 0; i<primaryCollection.size(); ++i ) std::cout << *primaryCollection[i];
}
int main()
{
CreateReport mime;
mime.load();
}
我正在尝试在我的 CreateReport class 中创建一个名为 load() 的函数,该函数将我的 graduate.dat 文件中的所有记录(数据)复制到我的静态记录指针向量中,称为主要收藏。我创建了一个 Record class,其中包含构成每个 Record 的变量,并且在 createReport.cc
的 load()
函数中,我尝试读取文件中的每一行,创建一个 Record object每行,将其添加到我的向量中,然后打印 primaryCollection 中的所有内容。
问题是每次我尝试使用 primaryCollection 时,我都会收到错误消息:
CreateReport.o: In function `CreateReport::CreateReport()':
CreateReport.cc:(.text+0x43): undefined reference to `CreateReport::primaryCollection'
CreateReport.o: In function `CreateReport::load()':
CreateReport.cc:(.text+0x2ac): undefined reference to `CreateReport::primaryCollection'
CreateReport.cc:(.text+0x31d): undefined reference to `CreateReport::primaryCollection'
CreateReport.cc:(.text+0x32f): undefined reference to `CreateReport::primaryCollection'
我在 createReport.cc 中提到 primaryCollection 的 4 次得到了 4 个未定义的引用。我不确定我是否正确地初始化了 primaryCollection 以及这是否是导致这些未定义引用的原因。我不知道这是否与我的问题有关,但 CreateReport 也是一个抽象 class 并且有一些名为 ReportOne、ReportTwo 等的子classes
primaryCollection 应该是 Record 指针的静态向量,我也不允许将 std::map 用于此任务。
对于此问题的任何帮助,我将不胜感激。我看了这个 post Undefined reference to static variable c++ 但我还是不太明白该怎么做。我不允许创建全局变量,我正在处理 collection 而不是单个变量。
我的graduate.dat文件格式如下,格式为<年省学位>
2000 AB Bachelor's
2005 AB Bachelor's
2005 MB College
每一行基本上代表一条记录。所以这里的第一个记录是 2000 AB Bachelor's
编辑:所以我根据评论对我的代码进行了更改,添加了行 vector
CreateReport.cc:13:34: error: conflicting declaration ‘std::vector<Record*> CreateReport::primaryCollection’
vector<Record*> CreateReport::primaryCollection;
^~~~~~~~~~~~~~~~~
In file included from CreateReport.cc:5:0:
CreateReport.h:23:33: note: previous declaration as ‘std::vector<Record*>* CreateReport::primaryCollection’
static std::vector<Record*>* primaryCollection; //STL vector of record pointers
^~~~~~~~~~~~~~~~~
CreateReport.cc:13:34: error: declaration of ‘std::vector<Record*>* CreateReport::primaryCollection’ outside of class is not definition [-fpermissive]
vector<Record*> CreateReport::primaryCollection;
有什么解决办法吗?
Record.h
#ifndef RECORD_H
#define RECORD_H
#include <iostream>
#include <string>
class Record{
public:
Record(int = 0, string = "", string = "");
~Record();
private:
int year;
string province;
string degree;
};
#endif
Record.cc
#include <iostream>
#include <string>
using namespace std;
#include "Record.h"
Record::Record(int i1, string s1, string s2) : year(i1), province(s1), degree(s2){}
Record::~Record(){}
CreateReport.h
#ifndef CREATEREPORT_H
#define CREATEREPORT_H
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>
#include <cstdlib>
#include "Record.h"
class CreateReport{
public:
CreateReport();
static void load();
protected:
static vector<Record*> primaryCollection; //STL vector of record pointers
};
#endif
CreateReport.cc
#include <iostream>
using namespace std;
#include <string>
#include "CreateReport.h"
vector<Record*> CreateReport::primaryCollection;
CreateReport::CreateReport(){
}
void CreateReport::load(){
int year;
string province, degree;
ostream_iterator<Record*> outItr(cout);
ifstream infile("graduate.dat", ios::in);
if (!infile) {
cout << "Error: could not open file" << endl;
exit(1);
}
while (infile >> year >> province >> degree) { //as long as were not at end of file
Record* record = new Record(year, province, degree); //create Record object with this data
primaryCollection->push_back(record); //undefined reference
}
cout<<endl<<"List of Records:"<<endl;
copy(primaryCollection->begin(), primaryCollection->end(), outItr); //2 undefined references
}
三大问题:
- 使用
std::vector<*Record>
会造成许多un-necessary困难; - 对于静态成员向量,需要在class之外进行额外的定义。
std::vector<Record> CreateReport::primaryCollection;
。这将清除未定义的错误消息。 - 使用复制到std::cout 不起作用,它不提供打印记录的方法。建议写个输出重载。
基于这些,我提供了一个版本如下(将所有 headers 混合在一起。)
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
using namespace std;
class Record{
public:
Record(int = 0, string = "", string = "");
~Record()=default;
friend std::ostream& operator<<(std::ostream&, const Record&);
private:
int year;
string province;
string degree;
};
// **** output overload for Record ***********
std::ostream& operator<<(std::ostream& os, const Record& rd)
{
os << "year = " << rd.year << " prov = " << rd.province << " degree = " << rd.degree << std::endl;
return os;
}
// ****** end of output overload **************
Record::Record(int i1, string s1, string s2) : year(i1), province(s1), degree(s2){}
//end of Record.cc
//
class CreateReport{
public:
CreateReport() = default;
void load();
protected:
static vector<Record> primaryCollection;
};
//***************** you need this line ********************
vector<Record> CreateReport::primaryCollection;
//*********************************************************
void CreateReport::load(){
int year;
string province, degree;
ifstream infile("graduate.dat", ios::in);
if (!infile) {
cout << "Error: could not open file" << endl;
exit(1);
}
while (infile >> year >> province >> degree) {
primaryCollection.push_back( Record(year, province, degree) );
}
cout<<endl<<"List of Records:"<<endl;
for (int i = 0; i<primaryCollection.size(); ++i ) std::cout << primaryCollection[i];
}
int main()
{
CreateReport mime;
mime.load();
}
第二个版本将 `Record*` 用于 `std::vector primaryCollection`。
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
using namespace std;
class Record{
public:
Record(int = 0, string = "", string = "");
~Record()=default;
friend std::ostream& operator<<(std::ostream&, const Record&);
private:
int year;
string province;
string degree;
};
// **** output overload for Record ***********
std::ostream& operator<<(std::ostream& os, const Record& rd)
{
os << "year = " << rd.year << " prov = " << rd.province << " degree = " << rd.degree << std::endl;
return os;
}
// ****** end of output overload **************
Record::Record(int i1, string s1, string s2) : year(i1), province(s1), degree(s2){}
//end of Record.cc
//
class CreateReport{
public:
CreateReport() = default;
void load();
protected:
static vector<Record*> primaryCollection; //STL vector of record pointers
};
//***************** you need this line ********************
std::vector<Record*> CreateReport::primaryCollection;
//*********************************************************
void CreateReport::load(){
int year;
string province, degree;
ifstream infile("graduate.dat", ios::in);
if (!infile) {
cout << "Error: could not open file" << endl;
exit(1);
}
while (infile >> year >> province >> degree) {
Record *a = new Record(year, province, degree);
primaryCollection.push_back( a );
}
cout<<endl<<"List of Records:"<<endl;
for (int i = 0; i<primaryCollection.size(); ++i ) std::cout << *primaryCollection[i];
}
int main()
{
CreateReport mime;
mime.load();
}