boost :: shared_ptr,继承后访问变量?

时间:2014-01-15 10:32:24

标签: c++ pointers inheritance boost shared-ptr

我使用的是MonkSVG库:

goal file

类对象定义为:

//mkSVG.h

namespace MonkSVG {
        using namespace std;

    class SVG;

        class ISVGHandler {
        public:

                typedef boost::shared_ptr<ISVGHandler> SmartPtr;

                ...

                ISVGHandler::SmartPtr                _handler;

        ...

然后该库的作者定义了another class

class OpenVG_SVGHandler : public ISVGHandler 

可以从ISVGHandler通过_handler访问SVG的变量。

我继承了我自己的2个类:第一个来自ISVGHandler,第二个来自SVG,第一个有自己的变量,但我无法直接访问它们。我找到的唯一解决方案是创建一个setter-getter方法,但即便如此,我还需要在根类和最后一个继承类中定义它们。

有没有更好的解决方案?

1 个答案:

答案 0 :(得分:0)

您应该使用ISVGHandler定义自己的处理程序,但是要添加和使用新函数,您也可以创建派生的SVG。你的SVG必须让你的处理程序工作,所以你可以同时制作它们,或者为了确保你初始化检查它。

#define MAKE_YOUR_OWN_HANDLER

#include <iostream>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>

// darned compiler not up to date
#define nullptr NULL

class ISVGHandler {
protected:
    ISVGHandler(){} // interface, must be derived
public:
    virtual ~ISVGHandler(){}

    typedef boost::shared_ptr<ISVGHandler> SmartPtr;
    void onPathBegin() {std::cout << "base onPathBegin" << std::endl;}
    void onPathEnd() {std::cout << "base onPathEnd" << std::endl;}
};

class OpenVG_SVGHandler : public ISVGHandler {
public:
    typedef boost::shared_ptr<OpenVG_SVGHandler> SmartPtr;
    static ISVGHandler::SmartPtr create() {
        return boost::make_shared<OpenVG_SVGHandler>();
    }

    void draw() {std::cout << "openvg draw" << std::endl;}
    void optimize() {std::cout << "openvg optimize" << std::endl;}
};

class WrongHandler : public ISVGHandler {
public:
    typedef boost::shared_ptr<OpenVG_SVGHandler> SmartPtr;
    static ISVGHandler::SmartPtr create() {
        return boost::make_shared<WrongHandler>();
    }

    void draw() {std::cout << "openvg draw" << std::endl;}
    void optimize() {std::cout << "openvg optimize" << std::endl;}
};

class SVG {
public:
    virtual ~SVG(){}

    bool initialize(ISVGHandler::SmartPtr handler) {
        _handler = handler; 
        std::cout << "base init" << std::endl; 
        return true;}

    void onPathBegin() {_handler->onPathBegin();}
    void onPathEnd()   {_handler->onPathEnd();}
private:
    ISVGHandler::SmartPtr _handler;
};

class OpenVG_SVG : public SVG {
private:
    OpenVG_SVGHandler * m_pOpenVG_Handler;

public:
#ifdef MAKE_YOUR_OWN_HANDLER
    OpenVG_SVG(){
        // use factory to make correct handler
        ISVGHandler::SmartPtr spBaseHandler (OpenVG_SVGHandler::create());

        // store known handler type for this class to use
        m_pOpenVG_Handler = reinterpret_cast<OpenVG_SVGHandler*>(spBaseHandler.get());

        // initialize the SVG base class
        initialize(spBaseHandler);
    }
#else
    OpenVG_SVG() : m_pOpenVG_Handler(nullptr) {}

    bool initialize(ISVGHandler::SmartPtr handler){
        try {
            m_pOpenVG_Handler = dynamic_cast<OpenVG_SVGHandler*>(handler.get());
            if (m_pOpenVG_Handler){
                std::cout << "openvg svg init" << std::endl;
                return SVG::initialize(handler);
            } else {
                std::cout << "wrong handler" << std::endl;
            }
        } catch (std::exception &e){
            std::cout << "wrong handler: " << e.what() << std::endl;
        }
        return false;
    }
#endif

    // write functions that are OpenVG specific in this class, using m_pOpenVG_Handler
    void draw() { m_pOpenVG_Handler->draw(); } // I'd check for null but that's not relevant to the question
    void optimize() {m_pOpenVG_Handler->optimize(); }

    // let the virtual functions handle all the other behavior.
};

int test_svg()
{
    OpenVG_SVG ovg;
#ifndef MAKE_YOUR_OWN_HANDLER
    ovg.initialize(OpenVG_SVGHandler::create());
#endif
    ovg.draw();
    ovg.onPathBegin();
    ovg.onPathEnd();
    ovg.optimize();

#ifndef MAKE_YOUR_OWN_HANDLER
    std::cout << "attempting to initialize with wrong handler:" << std::endl;
    OpenVG_SVG bad;
    if (bad.initialize(WrongHandler::create())){
        bad.draw();
    }
#endif
    return 0;
}