首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >c++导出纯抽象w/嵌套结构

c++导出纯抽象w/嵌套结构
EN

Stack Overflow用户
提问于 2012-02-18 23:46:39
回答 2查看 1.2K关注 0票数 6

我正在尝试建立一个类似于c#属性概念的语法糖。

我读过这篇文章:C#-like properties in native c++?。这很有帮助,但缺乏我想要的设计。我也不同意一些断言,即属性概念是糟糕的oo形式,因为我没有看到一组名为get_id()和set_id()的方法和一个操作符重载之间的区别,后者公开了相同的概念,允许在使用类时代码变得更干净,并且通常不鼓励对私有字段的公共访问,也使公共实现与私有设计脱钩。

然而,我想出的代码(受这个链接的启发)真的很混乱,很难维护。我想知道是否有人有任何建议来解决这个问题,或者更重要的是,知道一个更好的方法来解决这个问题。

代码语言:javascript
复制
class someClass
{
public:
    struct someProperty_struct{
        virtual someProperty_struct& operator=(const int&){return *this;}
        virtual operator int(){return 0;}
    }someProperty;
};

class derivedClass : someClass
{
    int i;
public:
    struct intProperty: someClass::someProperty_struct
    {
    protected:
        friend class derivedClass;
        derivedClass *outer;
    public:
        virtual someProperty_struct& operator=(const int& value){
            outer->i = value;
            return *this;}
        virtual operator int(){return outer->i;}
    };
    derivedClass()
    {
        intProperty p = intProperty();
        p.outer = this;
        someProperty = p;
    }
};

class consumerClass
{
public:
    someClass* data;
    consumerClass()
    {
        data = (someClass*)(new derivedClass());
    }
    void doSomething()
    {
        data->someProperty = 7;
        int x = data->someProperty;
    }
};

编辑1:我突然意识到,我并没有透露任何关于我的意图。它将用于调度程序,我们将对类中的所有数据进行大量的比较和分配。“someClass”实际上是数据上的一个接口(所需的方法非常少,应该是相对透明的大量数据)。它将在可执行文件链接的静态库中定义。“derivedClass”实际上是一个外部实现,在动态加载的dll中实现。这样做的原因是为了启用dll的“热交换”,而另一个dll实现了不同的文件后端。我们计划使用插件系统来加载xml、sqlite和mysql存储后端。

因此,基本上,我需要一个允许someClass成为由derivedClass继承的虚拟接口的设计,该接口通过工厂方法加载,通过插件系统传递,最后由consumerClass使用。

EN

Stack Overflow用户

回答已采纳

发布于 2012-02-22 10:07:17

所以基本上,我需要一个允许someClass成为虚拟接口的设计

如果我对你的理解是正确的,这个意图与你想出的解决方案相矛盾。虚拟继承只涉及虚拟成员函数。您不可能动态继承嵌套结构,因为它是C++中不支持的词法元编程的主题。

我的建议是仔细考虑,如果你能使你的目标不变。然后,对Builder/Factory设计模式的一些调整将允许您消除属性的使用。

您还可以考虑编写代码生成器。如果您获得一个好的标记关键字,这可能是容易的。

更新我添加了一些代码来澄清我的建议。

首先,我们准备一些辅助对象。它们应该放在库和客户端都可以访问的头文件中。这些对象将永远不会被修改。

GetSetProp <>- IGetSetProp <

代码语言:javascript
复制
template<class _Ty>
struct __declspec(novtable) IGetSetProp
{
    typedef std::tr1::shared_ptr<IGetSetProp<_Ty>> ptr_t;
    virtual void set_Prop(_Ty const& val);
    virtual _Ty get_Prop() const;
};

template<typename _Ty>
class PropFunctionAdapter : public IGetSetProp<_Ty>
{
    std::function<_Ty(void)> getter;
    std::function<void(_Ty const&)> setter;
public:
    PropFunctionAdapter(std::function<_Ty(void)> _getter, std::function<void(_Ty const&)> _setter)
        : getter(_getter)
        , setter(_setter)
    {
         // One may want to verify that getter and setter are not empty
    }

    virtual ~PropFunctionAdapter() throw() {}

    inline static std::tr1::shared_ptr<typename PropFunctionAdapter<_Ty>> Create(std::function<_Ty(void)> _getter, std::function<void(_Ty const&)> _setter)
    {
        return std::make_shared<typename PropFunctionAdapter<_Ty>>(_getter, _setter);
    }

public:
    void set_Prop(_Ty const& val)
    {
        setter(val);
    }

    _Ty get_Prop() const
    {
        return getter();
    }
};

template<class _Owner, class _Ty>
typename IGetSetProp<_Ty>::ptr_t CreateAdapter(_Owner& source, _Ty(_Owner::*getter)() const, void(_Owner::*setter)(_Ty const&))
{
    return PropFunctionAdapter<_Ty>::Create(
        std::tr1::bind(std::mem_fn(getter), &source),
        std::tr1::bind(std::mem_fn(setter), &source, std::tr1::placeholders::_1));
}

template<class _Ty>
class GetSetProp
{
    typename IGetSetProp<_Ty>::ptr_t prop;
public:
    GetSetProp(typename IGetSetProp<_Ty>::ptr_t _prop)
        : prop(_prop)
    {
    }

    GetSetProp<_Ty>& operator= (_Ty const& val)
    {
        prop->set_Prop(val);
        return *this;
    }

    operator _Ty() const
    {
        return prop->get_Prop();
    }
};

类似地,您可以定义GetProperty和SetProperty。

假设您有一个数据契约,其中包含两个字段压力:int和Description:string。然后定义数据契约:

代码语言:javascript
复制
class BaseClass
{
public:
    GetSetProp<int> Pressure;
    GetSetProp<std::string> Description;
protected:
    BaseClass(IGetSetProp<int>::ptr_t fieldA, IGetSetProp<std::string>::ptr_t fieldB)
        : Pressure(fieldA)
        , Description(fieldB)
    {
    }

    virtual ~BaseClass() throw() {}
};

及其在图书馆的实施情况:

代码语言:javascript
复制
class DerivedClass : public BaseClass
{
public:
    // Here you initialize fields assigning them correspondent setters and getters
    // You may define an ATL-like mapping in order to hide implementation details
    DerivedClass()
        : BaseClass(
            CreateAdapter(*this, &DerivedClass::get_Pressure, &DerivedClass::set_Pressure)
            , CreateAdapter(*this, &DerivedClass::get_Description, &DerivedClass::set_Description))
    {
    }

    virtual ~DerivedClass() throw() {}

private:
    void set_Pressure(int const& value)
    {
        val = value;
    }

    int get_Pressure() const
    {
        return val;
    }

    void set_Description(std::string const& description)
    {
        this->description = description;
    }

    std::string get_Description() const
    {
        return description;
    }

private:
    int val;
    std::string description;
};

// The client-side code
DerivedClass d;
BaseClass& b = d; 
b.Description = "Hello";
std::string descr = b.Description;
b.Pressure = 2;
int value = b.Pressure;
票数 2
EN
查看全部 2 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9345266

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档