还有另一种简单的方法来处理c ++属性吗?

时间:2015-07-25 02:04:21

标签: c++ c++11 properties c++14 generic-programming

我试图使用c ++属性,现在我坚持这个:

class a {
    protected:
        // wikipedia https://en.wikipedia.org/wiki/Property_(programming)#C.2B.2B
        template<class s, typename t>
        class getonly {
            protected:
                friend s;
                t value;
                t set(); // operator =...
            public:
                t get(); // t operator...
        };
};

class b : public a {
    public:
        getonly<b, int> id;
};

我想要的是这样的,其中getonly仅由typename(int)参数化,而不是类(b):

class b : public a {
    public:
        getonly<int> id;
};

这可能吗?任何人都可以帮助我吗?

2 个答案:

答案 0 :(得分:1)

您希望数据成员可以被任何代码读取,但只能由包含类更改。

通过模板提供friend的尝试不会在C ++ 11之前编译。这意味着不能轻易修改此代码以使用C ++ 03编译器(使用C ++ 03,可以通过例如设置者的所有者凭证参数来表示对修改的访问限制)。然而,这种担忧每天都变得不那么重要了。

您的代码已修改为编译,并且继承已从public更改为private(说b&并不是很有意义#34; is-an&#34; a):

class a {
protected:
    // wikipedia https://en.wikipedia.org/wiki/Property_(programming)#C.2B.2B
    template<class s, typename t>
    class getonly {
    protected:
        friend s;
        t value_;
    public:
        auto get() const -> t const& { return value_; }
        operator t const& () const { return value_; }

        getonly( t v ): value_( v ) {}
    };
};

class b : private a {
public:
    getonly<b, int> id;

    void set_id( int x ) { id.value_ = 2*x; }

    b(): id( 42 ) {}
};

#include <iostream>
auto main() -> int
{
    using namespace std;
    b obj;
    cout << obj.id << endl;
    obj.set_id( 333 );
    cout << obj.id << endl;
}

答案 1 :(得分:0)

首先,可以使用CRTP

完成此操作
template<typename s>
class a {
protected:
    // wikipedia https://en.wikipedia.org/wiki/Property_(programming)#C.2B.2B
    template<typename t>
    class getonly {
    protected:
        friend s;
        t value;
        t set(); // operator =...
    public:
        t get(); // t operator...
    };
};

class b : public a<b> {
public:
    getonly<int> id;
};

但是既然你提到了继承,你是否意识到friend声明不是继承的?如果这是你的目标,那么有一个更优雅的解决方案 - 不要将属性用作基类,而是作为特征:

template<typename T, typename F>
class property_impl
{
    friend F;
private:
    T value_;

protected:
    void set(T value)
    {
        value_ = value;
    }

public:
    T get()
    {
        return value_;
    }
};

template<typename F>
class property_traits
{
    template<typename T> using property = property_impl < T, F > ;
};

class foo : public property_traits < foo >
{
public:
    property<int> id_;
};

class bar : public foo, public property_traits < bar >
{
public:
    property<int> another_id_;

    void doStuff(foo f)
    {
        auto value =  f.id_.get();
        // f.id_.set(5); <-- fails since friend is not inherited

    }
};

int main(int argc, char** argv)
{
    foo f;
    auto value = f.id_.get();
    bar b;
    auto another_value = b.another_id_.get();
    b.doStuff(f);
    return 0;
}

这将使您能够在重新定义事实时继承和专门处理需要属性的每个类,只有专业化中使用的类类型才能修改该值。

再一次,也许你想要那个,我不确定。