提升text_iarchive不链接

时间:2017-01-26 18:41:44

标签: c++ boost

我正在尝试使用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

1 个答案:

答案 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>;