【问题标题】:boost::shared_ptr, access to a variable after inheritance?boost::shared_ptr,继承后访问变量?
【发布时间】:2014-01-15 10:32:24
【问题描述】:

我使用 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 

并且可以通过_handlerSVG访问ISVGHandler的变量。

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

有没有更好的解决方案?

【问题讨论】:

  • boost::dynamic_pointer_cast 浮现在脑海中,但如果你真的需要它,你应该重新考虑你的设计。如果您需要派生类的实例,请明确说明,而不是(可能很危险)强制转换。
  • 我假设你必须使用工厂生成器来构造处理程序,静态 ISVGHandler::SmartPtr OpenVG_ISVGHandler::create()?是否存在多种不同类型的 SVG 与多种不同类型的 SVGHandler 混淆的风险,或者程序总是只使用一种类型(OpenVG)?

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


【解决方案1】:

您应该使用 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;
}

【讨论】:

    猜你喜欢
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    • 2012-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多