web-dev-qa-db-ja.com

クラス変数:パブリックアクセス読み取り専用、プライベートアクセス読み取り/書き込み

ちょっと、そのソケットライブラリで作業していないウーピー。私は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の悪い習慣です。

追伸:基本的にポインターの知識を示し、それが完全かどうかを尋ねたい場合、どこに投稿すればよいですか?ありがとう!

47
FurryHead

もちろん次のことができます。

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

これはコピーを作成しません。 constへの参照を返します。

44
Alexandre C.

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 [〜#〜]:プロキシクラスを使用すると、要求した構文を正確に取得できます。

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になります。

47
Robᵩ

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

}

Getメソッドのようですが、短いです。興味深い質問...のようなもの。エクステントconst boolメンバー。多くのゲッターを節約できます...しかし、この機能を備えた言語はわかりません...

10

これはあなたが望むことをするかもしれません。

読み取り専用変数が必要で、クライアントがアクセス方法を変更する必要がないようにするには、このテンプレートクラスを試してください。

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を変更することはできません!ビット演算子と単項演算子も追加する必要があることを忘れないでください!これはあなたが始めるための単なる例です

5
Jonathan

メンバー変数を使用してそれを行う方法がありますが、おそらくそれはお勧めの方法ではありません。

書き込み可能なプライベートメンバーと、自身のクラスのメンバーをエイリアスする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」は増加せず、インライン化できるため、より多くのコードを生成しません。

2
CashCow

プライベートのままにして、値にアクセスする関数を作成する必要があります。

private:

    int x;

public:

    int X()
    {
        return x;
    }
1
NeilPearson

アクセスのためにC# properties を模倣したい場合があります(目的、目的の環境などによって異なります)。

class Foo
{
  private:
    int bar;

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

    void Getter() const
    {
      return bar;
    }
}
1
Brad Christie

メンバーをprivateにし、publicゲッターメソッドを提供する必要があります。

1
Jon

私が知っている唯一の方法は、c ++クラスのプライベートデータメンバーに読み取り専用アクセスを許可することです。あなたの場合、次のようになります:

int getx() const { return x; }

または

int x() const { return x; }

データメンバーをプライベートにすることで、デフォルトでクラス外のスコープにアクセスできなくなります(アクセス権なし)。本質的に、クラスのメンバーはプライベートデータメンバーへの読み取り/書き込みアクセス権を持っています(constであると指定していない場合)。クラスのfriendsは、プライベートデータメンバーへのアクセスを取得します。

アクセス指定子については here および/または good C++ book を参照してください。

1
yasouser

他の回答で述べたように、クラスメンバーをプライベートにし、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;
    }
}
0
Dinkydau Set

パブリックゲッター関数を作成します。

int getX(){ return x; }
0
hfitzwater