我正在尝试使用Boost将对象序列化为文件,并将保存的数据从文件读回到同一类型的另一个对象中。
但是,虽然我在Makefile中链接-lboost_serialization
,但在尝试编译项目时仍然会出现以下错误:
src/core/MainApp.o: In function `boost::archive::text_iarchive& boost::archive::detail::interface_iarchive<boost::archive::text_iarchive>::operator>><boost::archive::class_name_type>(boost::archive::class_name_type&)':
MainApp.cpp:(.text._ZN5boost7archive6detail18interface_iarchiveINS0_13text_iarchiveEErsINS0_15class_name_typeEEERS3_RT_[_ZN5boost7archive6detail18interface_iarchiveINS0_13text_iarchiveEErsINS0_15class_name_typeEEERS3_RT_]+0x2f): undefined reference to `boost::archive::text_iarchive_impl<boost::archive::text_iarchive>::load_override(boost::archive::class_name_type&, int)'
以下是I类尝试序列化的标题:
#ifndef RECORD_H_INC
#define RECORD_H_INC
//forward declaration of boost::serialization::access
namespace boost {
namespace serialization {
class access;
}
}
//includes
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
//Record class declaration
class Record
{
//public fields and methods
public:
//constructor
Record(); //initializes all fields to 0
//destructor
virtual ~Record();
//copy constructor
Record(const Record& r);
//assignment operator
Record& operator=(const Record& src);
//getter methods
int successes() const; //returns the success count
int failures() const; //returns the failure count
int attempts() const; //returns the total number of attempts made
double successPercentage() const; //returns the successes divided by the attempts times 100
//increment methods
void incrementSuccesses(); //increments the success count
void incrementFailures(); //increments the failure count
//protected fields and methods
protected:
int _successes; //the success count
int _failures; //the failure count
int _attempts; //the total attempt count
//make boost friendly
friend class boost::serialization::access;
//template method for serializing the class
template<typename Archive>
void serialize(Archive& ar, const unsigned version) {
ar & _successes & _failures & _attempts; //save the data to disk
}
};
#endif
以下是MainApp
类的标题:
#ifndef MAIN_APP_H
#define MAIN_APP_H
//includes
#include "../util/funcs.h"
#include "../record/Record.h"
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <string>
#include <fstream>
//class declaration
class MainApp {
//public fields and methods
public:
//constructor
MainApp();
//destructor
virtual ~MainApp();
//copy constructor
MainApp(const MainApp& ma);
//assignment operator
MainApp& operator=(const MainApp& src);
//methods
void run(); //runs the application
//protected fields and methods
protected:
Record* record; //the record storing the training data
std::string recordName; //the path to the file holding the record data
};
#endif
以下是MainApp
类的实现:
//include header
#include "MainApp.h"
//constructor
MainApp::MainApp()
: record(nullptr), recordName(" ") //init the fields
{
std::srand(std::time(NULL)); //seed the RNG
record = new Record(); //allocate a new Record object
//next we display a prompt
std::cout << "Enter the name of a training record to open." << std::endl;
std::cout << "If the specified record does not exist, it will be created." << std::endl;
std::cout << "Spaces and file extensions are not permitted in this entry." << std::endl;
std::cin >> recordName; //read in the record name
std::cout << "Welcome, " << recordName << "!" << std::endl;
recordName.append(".pre"); //add an extension
if(fileExistsAtPath(recordName)) { //if the record name actually represents a file
std::ifstream load(recordName); //get a stream object for deserialization
boost::archive::text_iarchive ar(load); //get an archive object for deserialization
ar >> record; //and deserialize the record
load.close(); //and close the loading stream
//display the stats
std::cout << "You have made " << record->attempts() << " attempts." << std::endl;
std::cout << "You have " << record->successes() << " successes and "
<< record->failures() << " failures." << std::endl;
std::cout << "You have a " << record->successPercentage() << "%% success rating." << std::endl;
} else {
std::ofstream save(recordName); //get a stream object for serialization
boost::archive::text_oarchive ar(save); //get an archive object for serialization
ar << record; //and serialize the record
save.close(); //and close the saving stream
}
}
//destructor
MainApp::~MainApp() {
if(record != nullptr) { //if the record is not null
delete record; //then delete it
record = nullptr; //and make it null
}
}
//copy constructor
MainApp::MainApp(const MainApp& ma)
: record(nullptr), recordName(ma.recordName) //init the record field to null and copy the recordName field
{
std::srand(std::time(NULL)); //seed the RNG
record = new Record(*ma.record); //copy the other Record object
//welcome the user
std::cout << "Welcome, " << recordName << "!" << std::endl;
//display the stats
std::cout << "You have made " << record->attempts() << " attempts." << std::endl;
std::cout << "You have " << record->successes() << " successes and "
<< record->failures() << " failures." << std::endl;
std::cout << "You have a " << record->successPercentage() << "%% success rating." << std::endl;
}
//assignment operator
MainApp& MainApp::operator=(const MainApp& src) {
*record = *src.record; //assign the record field
recordName = src.recordName; //assign the record name field
return *this; //return the object
}
//run method - runs the application
void MainApp::run() {
std::ofstream save(recordName); //used for saving data
boost::archive::text_oarchive ar(save); //used for saving data
bool shouldQuit = false; //checks whether or not the player should quit
while(!shouldQuit) { //loop while the player isn't quitting
int random = rand() % 37; //0 - 36
int predict = -1; //the player's prediction
std::cout << "Enter your prediction: "; //prompt for a prediction
std::cin >> predict; //read in the prediction
std::cout << std::endl; //newline
if(random == predict) { //if the answers match
std::cout << "Correct!" << std::endl; //then display a message
std::cout << "Your Prediction: " << predict << std::endl;
std::cout << "Correct Answer: " << random << std::endl;
record->incrementSuccesses(); //then increment the record's success count
} else { //if they don't
std::cout << "Too Bad!" << std::endl; //then display a message
std::cout << "Your Prediction: " << predict << std::endl;
std::cout << "Correct Answer: " << random << std::endl;
record->incrementFailures(); //then increment the record's failure count
}
//display stats
std::cout << "You have made " << record->attempts() << " attempts." << std::endl;
std::cout << "You have " << record->successes() << " successes and "
<< record->failures() << " failures." << std::endl;
std::cout << "You have a " << record->successPercentage() << "%% success rating." << std::endl;
ar << record; //serialize the record
char resp = 'y'; //the response of the player as to whether or not to quit
std::cout << "Continue? (y/n)" << std::endl; //prompt for continuing
std::cin >> resp; //read into the response
shouldQuit = (resp == 'y' ? false : true); //get the new shouldQuit value
}
save.close(); //close the save stream
}
//end of implementation
最后,这是我的Makefile:
CC=g++
CFLAGS=-c -Wall -Wno-unused-value -std=c++14
LIBFLAGS=-lboost_serialization
MAIN=$(shell ls src/*.cpp)
RECR=$(shell ls src/record/*.cpp)
CORE=$(shell ls src/core/*.cpp)
SOURCES=$(MAIN) $(RECR) $(CORE)
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=Trainer
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(OBJECTS) -o $(EXECUTABLE) $(LIBFLAGS)
mkdir obj
mkdir bin
mv -f $(EXECUTABLE) bin/
mv -f $(OBJECTS) obj/
.cpp.o:
$(CC) $(CFLAGS) $< -o $@
clean:
rm -rf bin
rm -rf obj
答案 0 :(得分:0)
您是否尝试添加:
#include <boost/archive/impl/basic_text_iarchive.ipp>
#include <boost/archive/impl/text_iarchive_impl.ipp>
#include <boost/archive/impl/basic_text_oarchive.ipp>
#include <boost/archive/impl/text_oarchive_impl.ipp>
我也尝试实例化模板,但不应该需要它
template class boost::archive::text_oarchive_impl<boost::archive::text_oarchive>;
template class boost::archive::text_iarchive_impl<boost::archive::text_iarchive>;