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

时间:2011-03-24 18:53:17

标签: c++ access-modifiers

Whoopee,暂时不在该套接字库上工作。我正在尝试用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;
}

我的问题,简明,是如何允许x内的f()完全访问权限,但允许来自其他任何地方的只读访问权限,例如int newint = temp.x;允许,temp.x = 5;不允许?像一个const变量,但可以从f() ...

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

P.S。如果我只是想基本上展示我对指针的知识并询问它是否完整,我会在哪里发帖?谢谢!

12 个答案:

答案 0 :(得分:47)

虽然我认为返回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中的只读main

答案 1 :(得分:42)

当然你可以:

class MyClass
{
    int x_;

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

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

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

public:
    const std::vector<double>& x() const { return x_; }
};

这不会制作任何副本。它会返回 reference to const

答案 2 :(得分:10)

一个简单的解决方案,比如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

}

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

答案 3 :(得分:5)

这可能会做你想要的。

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

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! 请记住,您还需要添加按位和一元运算符!这只是一个让你入门的例子

答案 4 :(得分:2)

有一种方法可以使用成员变量来完成它,但它可能不是这样做的明智之举。

拥有一个可写的私有成员,以及一个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”则不会,并且可以内联,因此它也不会生成更多的代码。

答案 5 :(得分:1)

您需要制作成员private并提供public getter方法。

答案 6 :(得分:1)

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

int getx() const { return x; }

int x() const { return x; }

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

在访问说明符上提及here和/或任何good C++ book

答案 7 :(得分:1)

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

private:

    int x;

public:

    int X()
    {
        return x;
    }

答案 8 :(得分:1)

您可能希望模仿C#properties进行访问(取决于您的目标,预期环境等)。

class Foo
{
  private:
    int bar;

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

    void Getter() const
    {
      return bar;
    }
}

答案 9 :(得分:0)

写一个公共的getter函数。

int getX(){ return x; }

答案 10 :(得分:0)

如其他答案所述,您可以通过将类成员设为私有并定义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;
    }
}

答案 11 :(得分:-1)

  

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

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

以下是要求访问

  

cout&lt;&lt; temp.x&lt;&lt; ENDL;

但这里不是 -

  

int myint = temp.x;

这听起来很矛盾。