我试图使用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;
};
这可能吗?任何人都可以帮助我吗?
答案 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;
}
这将使您能够在重新定义事实时继承和专门处理需要属性的每个类,只有专业化中使用的类类型才能修改该值。
再一次,也许你想要那个,我不确定。