C++ 在C+中创建只读(公共)类成员+;

C++ 在C+中创建只读(公共)类成员+;,c++,getter-setter,reflection,C++,Getter Setter,Reflection,我来自ActionScript3这样的语言背景,我们有一种特殊的方式来定义一个成员变量,既可以作为实例,也可以作为设置/获取受保护或私有成员值的方法。让我举一个例子: 在一个类中,我们可以这样说: private var _myString:String; public get myString():String { return _myString; } public set myString(newValue:String):void { //Do some super

我来自ActionScript3这样的语言背景,我们有一种特殊的方式来定义一个成员变量,既可以作为实例,也可以作为设置/获取受保护或私有成员值的方法。让我举一个例子:

在一个类中,我们可以这样说:

private var _myString:String;

public get myString():String 
{
    return _myString;
}

public set myString(newValue:String):void
{
    //Do some super secret member protection n' stuff
    _myString = newValue;
}
template<typename T>
class AbstractGetter {
  T &refT;
public:
  operator const T() const { return refT; }
  AbstractGetter(T &refT_) : refT(refT_) { }
};

class Foo {
  int foo_private;
public:
  AbstractGetter<int> foo;

  Foo() : foo(foo_private) { }
};
在这个物体之外,我可以做以下事情:

trace(myClass.myString); //Output whatever _myString is. (note the lack of (). It's being accessed like property not a method...
更进一步,我可以做一些类似于删除“publicsetmystring”方法的事情,因此如果有人试图对我的类执行此操作:

myClass.myString = "Something"; //Try to assign - again note the lack of ()
它将抛出一个错误,让用户知道该属性是只读的

因为我使用C++,它比ActionScript 3更为可怕,我想知道我如何模仿这种行为。我不想使用一堆肮脏的

getVariable()
setVariable()
方法。我希望通过一些操作符重载的诡计,我可以在这里实现完全相同的事情。注意:我是一个noob,所以请这样称呼我。:)

更新
我想解释这一点最简单的方法是,我尝试使用getter和setter,但通过赋值而不是用括号()来调用它们。

要获得您想要的行为并不是不可能的。但这也不一定是个好主意

原则上,您可以这样做:

private var _myString:String;

public get myString():String 
{
    return _myString;
}

public set myString(newValue:String):void
{
    //Do some super secret member protection n' stuff
    _myString = newValue;
}
template<typename T>
class AbstractGetter {
  T &refT;
public:
  operator const T() const { return refT; }
  AbstractGetter(T &refT_) : refT(refT_) { }
};

class Foo {
  int foo_private;
public:
  AbstractGetter<int> foo;

  Foo() : foo(foo_private) { }
};
模板
类抽象getter{
T&refT;
公众:
运算符const T()const{return refT;}
抽象getter(T&refT):refT(refT){
};
福班{
int foo_private;
公众:
葛德福;
Foo():Foo(Foo_private){}
};
但是:这里的AbstractGetter需要额外的内存
sizeof(int&)
。这也是一个相当丑陋的黑客行为——如果您开始需要表示任何比引用更复杂的东西(也许您的getter需要一些逻辑?),那么语法或内存开销就会变得更糟


这样,使用GETter函数是普通C++风格,而不是像这样的黑客。

< P>对不起,用C++,语法糖不存在>,这意味着你必须自己实现GET/SET方法。 因此,在您的例子中,您必须实现一个getVariable()方法,而不使用它的等效Set方法,以便使其成为只读的


请不要求助于宏使其看起来像您有一些只读属性。5年后,当他们读代码时,会让人恼火。

如果我正确地理解了你的问题,你想用C++术语创建<代码> const < /Cuth> public成员变量。
class myClass
{
//...
public:
  const std::string myString;

  myClass(std::string s) : myString(s) {}
};
现在,当您声明
class
对象时,
myClass::myString
将被初始化,并且在其整个生命周期内保持不可变(只读)

作为这种方法的副作用,现在
myClass
对象不能是默认可分配的。i、 e

myClass o1("s"), o2("t");
o1 = o2; // error

实际上,使用模板灵长类动物是可能的

如果您想要一个只读变量,但不希望客户端必须更改其访问方式,请尝试以下模板类:

template<typename MemberOfWhichClass, typename primative>                                       
class ReadOnly {
    friend MemberOfWhichClass;
public:
    inline operator primative() const                 { return x; }

    template<typename number> inline bool   operator==(const number& y) const { return x == y; } 
    template<typename number> inline number operator+ (const number& y) const { return x + y; } 
    template<typename number> inline number operator- (const number& y) const { return x - y; } 
    template<typename number> inline number operator* (const number& y) const { return x * y; }  
    template<typename number> inline number operator/ (const number& y) const { return x / y; } 
    template<typename number> inline number operator<<(const number& y) const { return x <<y; }
    template<typename number> inline number operator>>(const number& y) const { return x >> y; }
    template<typename number> inline number operator^ (const number& y) const { return x ^ y; }
    template<typename number> inline number operator| (const number& y) const { return x | y; }
    template<typename number> inline number operator& (const number& y) const { return x & y; }
    template<typename number> inline number operator&&(const number& y) const { return x &&y; }
    template<typename number> inline number operator||(const number& y) const { return x ||y; }
    template<typename number> inline number operator~() const                 { return ~x; }

protected:
    template<typename number> inline number operator= (const number& y) { return x = y; }       
    template<typename number> inline number operator+=(const number& y) { return x += y; }      
    template<typename number> inline number operator-=(const number& y) { return x -= y; }      
    template<typename number> inline number operator*=(const number& y) { return x *= y; }      
    template<typename number> inline number operator/=(const number& y) { return x /= y; }      
    template<typename number> inline number operator&=(const number& y) { return x &= y; }
    template<typename number> inline number operator|=(const number& y) { return x |= y; }
    primative x;                                                                                
};      
模板
类只读{
谁的朋友;
公众:
内联运算符primative()常量{return x;}
模板内联布尔运算符==(常量编号&y)常量{return x==y;}
模板内联编号运算符+(常量编号&y)常量{返回x+y;}
模板内联数字运算符-(const number&y)const{return x-y;}
模板内联编号运算符*(常量编号&y)常量{return x*y;}
模板内联编号运算符/(常量编号&y)常量{返回x/y;}
模板内联编号运算符y;}
模板内联数字运算符^(const number&y)const{return x^y;}
模板内联数字运算符|(const number&y)const{return x | y;}
模板内联数字运算符&(const number&y)const{return x&y;}
模板内联数字运算符&&(const number&y)const{return x&&y;}
模板内联数字运算符| |(const number&y)const{return x | | y;}
模板内联数字运算符~()常量{return~x;}
受保护的:
模板内联编号运算符=(常量编号&y){return x=y;}
模板内联编号运算符+=(常量编号&y){return x+=y;}
模板内联编号运算符-=(常量编号&y){return x-=y;}
模板内联编号运算符*=(常量编号&y){return x*=y;}
模板内联编号运算符/=(常量编号&y){return x/=y;}
模板内联编号运算符&=(常量编号&y){返回x&=y;}
模板内联编号运算符|=(常量编号&y){返回x |=y;}
灵长类x;
};      
示例用法:

class Foo {
public:
    ReadOnly<Foo, int> x;
};
class-Foo{
公众:
只读x;
};
现在您可以访问Foo.x,但不能更改Foo.x!
请记住,您还需要添加位运算符和一元运算符!这只是一个开始的例子

C++非常灵活,所以你可以做很多讨厌的事情。 这是可能的,但需要更多的打字

这是一个包装器模板

// element wrapper for creating a getter and setter.
template <typename Base, typename T>
class getterSetter{
  T value;
  // below members required for setting up setter logic in owner class.
  Base *parent;            //owner object pointer
  bool (Base::*setter)(T&); //setter callback return true to set, false to not set.

public:
  getterSetter(T& v, Base *p, bool (Base::*set)(T&))
    : value(v),
      parent(p),
      setter(set)
  {} // read-write constructor.                                                                                                             
  getterSetter(T& v): value(v),parent(NULL), setter(NULL) {} // read only constructor.                                                      

  // setter implemented via operator overloading of = operator.
  const getterSetter& operator=(const T& v) {
    if (this->parent && this->setter && (parent->*(this->setter))(v)) {
      value = v;
    }
    else {
      // throw an exception here.                                                                                                           
    }
    return *this;
  }

  // cast sometimes helps for a getter.
  operator T() const{
    return value;
  }
};
会有用的


<>虽然这是可以做到的,但是在C++中做不是好事。它为每个坏属性使用两个额外的指针内存。还需要编写更多的运算符重载来处理STL和外部代码。可能有更好的方法。

AbstractGetter
中添加一个私有setter,让它将
Foo
作为第二个模板参数并与
Foo
交朋友,然后让它直接存储
T
怎么样?我同意。就连我都不懂这些东西……:)@JamesMcNellis,好吧,我承认这会更好,但它不会让你在getter中加入任何智能:)我找到了这个答案:。用户“j_random_hacker”的回答似乎与我所说的差不多