C++ 类变量:公共访问只读,但私有访问读/写

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5424042/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 18:08:18  来源:igfitidea点击:

Class variables: public access read-only, but private access read/write

c++access-modifiers

提问by FurryHead

Whoopee, not working on that socket library for the moment. I'm trying to educate myself a little more in C++.

哎呀,暂时不在那个套接字库上工作。我正在尝试更多地用 C++ 教育自己。

With classes, is there a way to make a variable read-only to the public, but read+write when accessed privately? e.g. something like this:

对于类,有没有办法使变量对公众只读,但在私下访问时可以读+写?例如这样的事情:

class myClass {
    private:
    int x; // this could be any type, hypothetically

    public:
    void f() {
        x = 10; // this is OK
    }
}

int main() {
    myClass temp;

    // I want this, but with private: it's not allowed
    cout << temp.x << endl;


    // this is what I want:

    // this to be allowed
    temp.f(); // this sets x...

    // this to be allowed
    int myint = temp.x;

    // this NOT to be allowed
    temp.x = myint;
}

My question, condensed, is how to allow full access to xfrom within f()but read-only access from anywhere else, i.e. int newint = temp.x;allowed, but temp.x = 5;not allowed? like a const variable, but writable from f()...

简而言之,我的问题是如何允许x从内部完全访问f()但从其他任何地方只读访问,即int newint = temp.x;允许但temp.x = 5;不允许?就像一个 const 变量,但可以从f()...

EDIT: I forgot to mention that I plan to be returning a large vector instance, using a getX() function would only make a copy of that and it isn't really optimal. I could return a pointer to it, but that's bad practice iirc.

编辑:我忘了提到我计划返回一个大的向量实例,使用 getX() 函数只会复制它,它并不是真正的最佳选择。我可以返回一个指向它的指针,但这是不好的做法 iirc。

P.S.: Where would I post if I just want to basically show my knowledge of pointers and ask if it's complete or not? Thanks!

PS:如果我只是想基本上展示我对指针的了解并询问它是否完整,我会在哪里发布?谢谢!

采纳答案by Alexandre C.

Of course you can:

当然可以:

class MyClass
{
    int x_;

public:
    int x() const { return x_; }
};

If you don't want to make a copy (for integers, there is no overhead), do the following:

如果您不想复制(对于整数,没有开销),请执行以下操作:

class MyClass
{
    std::vector<double> v_;

public:
    decltype(v)& v() const { return v_; }
};

or with C++98:

或使用 C++98:

class MyClass
{
    std::vector<double> v_;

public:
    const std::vector<double>& v() const { return v_; }
};

This does not make any copy. It returns a reference to const.

这不会制作任何副本。它返回对 const引用

回答by Rob?

While I think a getter function that returns const T&is the better solution, you can have almost precisely the syntax you asked for:

虽然我认为返回的 getter 函数const T&是更好的解决方案,但您几乎可以使用您要求的语法:

class myClass {
    private:
    int x_; // Note: different name than public, read-only interface

    public:
    void f() {
        x_ = 10; // Note use of private var
    }
    const int& x;
    myClass() : x_(42), x(x_) {} // must have constructor to initialize reference
};

int main() {
    myClass temp;

    // temp.x is const, so ...
    cout << temp.x << endl; // works
    // temp.x = 57;  // fails

}

EDIT: With a proxy class, you can get precisely the syntax you asked for:

编辑:使用代理类,您可以准确地获得您要求的语法:

class myClass {
public:

    template <class T>
    class proxy {
        friend class myClass;
    private:
        T data;
        T operator=(const T& arg) { data = arg; return data; }
    public:
        operator const T&() const { return data; }
    };

    proxy<int> x;
    // proxy<std::vector<double> > y;


    public:
    void f() {
        x = 10; // Note use of private var
    }
};

temp.xappears to be a read-write intin the class, but a read-only intin main.

temp.xint在类中似乎是可读写的,但intmain.

回答by Miguel Angel Pons

A simple solution, like Rob, but without contructor:

一个简单的解决方案,如 Rob,但没有构造函数:

class myClass {
    private:
    int m_x=10; // Note: different name than public, read-only interface
    public:
    const int& x=m_x;

};

int main() {
    myClass temp;

    // temp.x is const, so ...
    cout << temp.x << endl; // works
    // temp.x = 57;  // fails

}

Is like a get methode, but shorter. Interesant question ... something like. extent const bool member; can save a lot of getters ...but I don't know languages with this feature...

就像一个 get 方法,但更短。有趣的问题......类似的东西。范围 const bool 成员;可以节省很多 getter ......但我不知道有这个功能的语言......

回答by Jonathan

This may do what you want.

这可能会做你想做的。

If you want a readonly variable but don't want the client to have to change the way they access it, try this templated class:

如果您想要一个只读变量但不希望客户端必须更改他们访问它的方式,请尝试使用这个模板化类:

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;                                                                                
};      

Example Use:

使用示例:

class Foo {
public:
    ReadOnly<Foo, int> x;
};

Now you can access Foo.x, but you can't change Foo.x! Remember you'll need to add bitwise and unary operators as well! This is just an example to get you started

现在您可以访问 Foo.x,但您无法更改 Foo.x!请记住,您还需要添加按位和一元运算符!这只是让您入门的示例

回答by CashCow

There is a way to do it with a member variable, but it is probably not the advisable way of doing it.

有一种方法可以使用成员变量来做到这一点,但这可能不是明智的做法。

Have a private member that is writable, and a const reference public member variable that aliases a member of its own class.

有一个可写的私有成员,以及一个常量引用公共成员变量,它为其自己的类的成员命名。

class Foo
{
  private:
      Bar private_bar;

  public:
      const Bar& readonly_bar; // must appear after private_bar
                              // in the class definition

  Foo() :
       readonly_bar( private_bar )
  {
  }
};

That will give you what you want.

那会给你你想要的。

void Foo::someNonConstmethod()
{
    private_bar.modifyTo( value );
}

void freeMethod()
{
    readonly_bar.getSomeAttribute();
}

What you can do, and what you should do are different matters. I'm not sure the method I just outlined is popular and would pass many code reviews. It also unnecessarily increases sizeof(Foo) (albeit by a small amount) whereas a simple accessor "getter" would not, and can be inlined, so it won't generate more code either.

你能做什么,你应该做什么是不同的事情。我不确定我刚刚概述的方法是否流行,是否会通过许多代码。它也不必要地增加了 sizeof(Foo)(尽管增加了少量),而简单的访问器“getter”不会,并且可以内联,因此它也不会生成更多代码。

回答by NeilPearson

You would have to leave it private and then make a function to access the value;

您必须将其设为私有,然后创建一个函数来访问该值;

private:

    int x;

public:

    int X()
    {
        return x;
    }

回答by Brad Christie

You may want to mimic C# propertiesfor access (depending what you're going for, intended environment, etc.).

您可能想要模拟 C#属性以进行访问(取决于您的目的、预期环境等)。

class Foo
{
  private:
    int bar;

  public:
    __declspec( property( get = Getter ) ) int Bar;

    void Getter() const
    {
      return bar;
    }
}

回答by yasouser

The only way I know of granting read-only access to private data members in a c++ class is to have a public function. In your case, it will like:

我所知道的授予对 c++ 类中私有数据成员只读访问权限的唯一方法是拥有一个公共函数。在你的情况下,它会喜欢:

int getx() const { return x; }

int getx() const { return x; }

or

或者

int x() const { return x; }.

int x() const { return x; }.

By making a data member private you are by default making it invisible (a.k.a no access) to the scope outside of the class. In essence, the members of the class have read/write access to the private data member (assuming you are not specifying it to be const). friends of the class get access to the private data members.

通过将数据成员设为私有,您默认情况下使其对类外的范围不可见(也就是无权访问)。本质上,类的成员对私有数据成员具有读/写访问权限(假设您没有将其指定为const)。friend类的 s 可以访问私有数据成员。

Refer hereand/or any good C++ bookon access specifiers.

请参阅此处和/或任何关于访问说明符的优秀 C++ 书籍

回答by Dinkydau Set

As mentioned in other answers, you can create read only functionality for a class member by making it private and defining a getter function but no setter. But that's a lot of work to do for every class member.

如其他答案中所述,您可以通过将类成员设为私有并定义 getter 函数但不定义 setter 来为类成员创建只读功能。但这对每个班级成员来说都是很多工作要做。

You can also use macros to generate getter functions automatically:

您还可以使用宏来自动生成 getter 函数:

#define get_trick(...) get_
#define readonly(type, name) \
private: type name; \
public: type get_trick()name() {\
    return name;\
}

Then you can make the class this way:

然后你可以这样创建类:

class myClass {
    readonly(int, x)
}

which expands to

扩展到

class myClass {
    private: int x;
    public: int get_x() {
        return x;
    }
}

回答by Jon

You need to make the member privateand provide a publicgetter method.

您需要创建成员private并提供一个publicgetter 方法。