2014-01-15 33 views
0

我使用MonkSVG库:boost :: shared_ptr,继承后访问变量?

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 

,则有可能通过_handler从0开始访问变量。

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

有没有更好的解决方案?

+1

'boost :: dynamic_pointer_cast'出现在脑海中,但如果您确实需要这一点,则应该重新考虑您的设计。如果你需要派生类的一个实例,那么明确地说出来,而不是(可能很危险)。 – arne

+0

我假设你必须使用工厂生成器来构造处理程序,static ISVGHandler :: SmartPtr OpenVG_ISVGHandler :: create()?是否存在多种不同类型的SVG与多种不同类型的SVGHandler混合在一起的风险,还是程序总是只使用一种类型(OpenVG)? –

回答

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; 
}