6.3 Case Studies - PIMPL

demo_pimpl_A.hpp

// demo_pimpl_A.hpp

// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
// Use, modification and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

// class whose declaration is hidden by a pointer
struct B;

struct A {
    // class a contains a pointer to a "hidden" declaration
    B *pimpl;
    template<class Archive>
    void serialize(Archive & ar, const unsigned int file_version);
    A();
    ~A();
};

#endif // BOOST_SERIALIZATION_EXAMPLE_DEMO_PIMPL_A_HPP

在这段文本中,有一个名为demo_pimpl.cpp的程序,用来演示如何使用PIMPL。文件demo_pimpl_A.hpp包含了一个类A的声明,该类通过包含一个指向结构体B的指针来隐藏其实现细节。但是,B的具体定义在另一个单独编译的模块demo_pimpl_A.cpp中。

demo_pimpl_A.cpp

// demo_pimpl_A.cpp
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>

#include "demo_pimpl_A.hpp"

// "hidden" definition of class B
struct B {
    int b;
    template<class Archive>
    void serialize(Archive & ar, const unsigned int /* file_version */){
        ar & b;
    }
};

A::A() :
    pimpl(new B)
{}
A::~A(){
    delete pimpl;
}
// now we can define the serialization for class A
template<class Archive>
void A::serialize(Archive & ar, const unsigned int /* file_version */){
    ar & pimpl;
}

这种设计的优势包括:
1.类型B可以在不包含其头文件的情况下使用。
2.类型B的实现可以更改而不会引发大规模的重新编译。

然而,在链接时,会出现错误,因为两个符号未定义:

void A::serialize(boost::archive::text_oarchive & ar, const unsigned int file_version);
void A::serialize(boost::archive::text_iarchive & ar, const unsigned int file_version);

问题在于,在编译上述代码时,serialize模板没有被实例化,因为不知道要与哪种类型的归档一起使用。因此,在尝试链接时,这些函数会“丢失”。解决方法是显式实例化将要使用的归档类型的序列化代码。在示例中,通过在任何*.cpp文件中包含以下代码来实现:

// without the explicit instantiations below, the program will
// fail to link for lack of instantiantiation of the above function
// note: the following failed to fix link errors for vc 7.0 !
template void A::serialize<boost::archive::text_iarchive>(
    boost::archive::text_iarchive & ar, 
    const unsigned int file_version
);
template void A::serialize<boost::archive::text_oarchive>(
    boost::archive::text_oarchive & ar, 
    const unsigned int file_version
);

这样,程序就能够成功链接。不过,这种方法的缺点是必须事先知道要与隐藏的序列化一起使用哪些归档类型,因为它依赖于显式实例化模板,而这可能会导致平台依赖性。

demo_pimpl.cpp

// demo_pimpl.cpp
#include <sstream>

#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>

#include "demo_pimpl_A.hpp"

int main(int argc, char* argv[])
{
    std::stringstream ss;

    const A a;
    {
        boost::archive::text_oarchive oa(ss);
        oa << a;
    }
    A a1;
    {
        boost::archive::text_iarchive ia(ss);
        ia >> a1;
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值