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

发布于 2024-10-26 11:39:12 字数 908 浏览 5 评论 0原文

哎呀,暂时不处理该套接字库。我正在尝试更多地学习 C++。

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

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

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

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

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

Whoopee, not working on that socket library for the moment. I'm trying to educate myself a little more in 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 x from 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()...

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.

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!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

无人问我粥可暖 2024-11-02 11:39:12

当然可以:

class MyClass
{
    int x_;

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

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

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

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

或使用 C++98:

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

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

这不会进行任何复制。它返回对 const 的引用

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:

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.

万劫不复 2024-11-02 11:39:12

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

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

}

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

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.x 在类中似乎是一个可读写的 int,但它是一个只读的 int中。

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

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.x appears to be a read-write int in the class, but a read-only int in main.

一曲爱恨情仇 2024-11-02 11:39:12

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

class myClass {
private:
    int m_x = 10; // Note: name modified from read-only reference in public interface
public:
    const int& x = m_x;
};

int main() {
    myClass temp;

    cout << temp.x << endl; //works.
    //temp.x = 57;  //fails.
}

它更像 get 方法,但更短。

常量指针很简单,并且应该适用于您可以指向的所有类型。

A simple solution, like Rob's, but without constructor:

class myClass {
private:
    int m_x = 10; // Note: name modified from read-only reference in public interface
public:
    const int& x = m_x;
};

int main() {
    myClass temp;

    cout << temp.x << endl; //works.
    //temp.x = 57;  //fails.
}

It is more like get method, but shorter.

Constant pointer is simple, and should work at all types you can make pointer to.

温柔戏命师 2024-11-02 11:39:12

这可能会做你想做的事。

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

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

示例使用:

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

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

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

佞臣 2024-11-02 11:39:12

您可能想模仿 C# 属性 进行访问(取决于您的用途)目标、预期环境等)。

class Foo
{
  private:
    int bar;

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

    void Getter() const
    {
      return bar;
    }
}

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

class Foo
{
  private:
    int bar;

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

    void Getter() const
    {
      return bar;
    }
}

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

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

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

那会给你你想要的。

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

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

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

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.

风渺 2024-11-02 11:39:12

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

private:

    int x;

public:

    int X()
    {
        return x;
    }

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

private:

    int x;

public:

    int X()
    {
        return x;
    }
梦里人 2024-11-02 11:39:12

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

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

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

然后您可以这样创建类:

class myClass {
    readonly(int, x)
}

扩展为

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

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.

You can also use macros to generate getter functions automatically:

#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;
    }
}
泅渡 2024-11-02 11:39:12

您需要将成员设为 private 并提供一个 public getter 方法。

You need to make the member private and provide a public getter method.

烟若柳尘 2024-11-02 11:39:12

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

int getx() const { return x; }

int x() const { return x; }

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

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

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:

int getx() const { return x; }

or

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.

Refer here and/or any good C++ book on access specifiers.

背叛残局 2024-11-02 11:39:12

编写一个公共 getter 函数。

int getX(){ return x; }

Write a public getter function.

int getX(){ return x; }
不知在何时 2024-11-02 11:39:12

我有一个类似的问题。这是我的解决方案:

enum access_type{readonly, read_and_write};

template<access_type access>
class software_parameter;

template<>
class software_parameter<read_and_write>{
protected:
    static unsigned int test_data;
};

template<>
class software_parameter<readonly> : public software_parameter<read_and_write>{
public:
    static const unsigned int & test_data;
};

class read_and_write_access_manager : public software_parameter<read_and_write>{
    friend class example_class_with_write_permission;
};

class example_class_with_write_permission{
public:
    void set_value(unsigned int value);
};

.cpp 文件:

unsigned int software_parameter<read_and_write>::test_data=1;
const unsigned int & software_parameter<readonly>::test_data=software_parameter<read_and_write>::test_data;

void example_class_with_write_permission::set_value(unsigned int value){software_parameter<read_and_write>::test_data=value;};

这个想法是,每个人都可以读取软件参数,但只有类 read_and_write_access_manager 的朋友才允许更改软件参数。

I had a similiar problem. Here is my solution:

enum access_type{readonly, read_and_write};

template<access_type access>
class software_parameter;

template<>
class software_parameter<read_and_write>{
protected:
    static unsigned int test_data;
};

template<>
class software_parameter<readonly> : public software_parameter<read_and_write>{
public:
    static const unsigned int & test_data;
};

class read_and_write_access_manager : public software_parameter<read_and_write>{
    friend class example_class_with_write_permission;
};

class example_class_with_write_permission{
public:
    void set_value(unsigned int value);
};

And the .cpp file:

unsigned int software_parameter<read_and_write>::test_data=1;
const unsigned int & software_parameter<readonly>::test_data=software_parameter<read_and_write>::test_data;

void example_class_with_write_permission::set_value(unsigned int value){software_parameter<read_and_write>::test_data=value;};

The idea is, that everyone can read the software parameter, but only the friends of the class read_and_write_access_manager are allowed to change software parameter.

瞎闹 2024-11-02 11:39:12

但是 temp.x = 5;不允许?

这是在发布的代码片段中不允许的任何方式,因为它无论如何都被声明为私有并且只能在类范围内访问。

这里要求访问

cout <<温度.x <<结束;

但这里不是为了-

int myint = temp.x;

这听起来很矛盾。

but temp.x = 5; not allowed?

This is any how not allowed in the snippet posted because it is anyhow declared as private and can be accessed in the class scope only.

Here are asking for accessing

cout << temp.x << endl;

but here not for-

int myint = temp.x;

This sounds very contradictory.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文