web-dev-qa-db-ja.com

クラスの関数で 'const'を使用する

クラスで関数の後に置かれるconstキーワードの多くの使用を見たので、それが何であるか知りたいと思いました。私はここでsmthを読みました: http://duramecho.com/ComputerInformation/WhyHowCppConst.html

これは、関数が「オブジェクト内のメンバー変数を変更しようとする可能性がある」ため、constが使用されていることを示しています。これがtrueの場合は、あらゆる場所で使用する必要があります。メンバー変数を変更したり、変更したりしたくないからです。

class Class2
{ void Method1() const;
  int MemberVariable1;} 

それでは、constの実際の定義と使用法は何ですか?

26
ggg

Constメソッドは、constオブジェクトで呼び出すことができます。

class CL2
{
public:
    void const_method() const;
    void method();

private:
    int x;
};


const CL2 co;
CL2 o;

co.const_method();  // legal
co.method();        // illegal, can't call regular method on const object
o.const_method();   // legal, can call const method on a regulard object
o.method();         // legal

さらに、constメソッドはオブジェクトの状態を変更してはならず、これらの問題をキャッチすることもコンパイラーに通知します。

void CL2::const_method() const
{
    x = 3;   // illegal, can't modify a member in a const object
}

変更可能な修飾子を使用することによる上記のルールには例外がありますが、その領域に入る前に、まずconstの正確さを理解する必要があります。

37

他の人はconstメンバー関数についてのあなたの質問の技術的な側面に答えましたが、ここには全体像があります-そしてそれは const correctness の考え方です。

一言で言えば、constの正確さは、コードのセマンティクスを明確にし、強制することです。簡単な例を見てみましょう。この関数宣言を見てください。

_bool DoTheThing(char* message);
_

他の誰かがこの関数を書いて、それを呼び出す必要があるとします。 charバッファに対してDoTheThing()が何をするか知っていますか?メッセージをファイルに記録するだけの場合もあれば、文字列を変更する場合もあります。関数の宣言を見ただけでは、呼び出しのセマンティクスはわかりません。関数が文字列を変更しない場合、宣言はconstが正しくありません。

関数を正しくconstにすることにも実用的な価値があります。つまり、呼び出しのコンテキストによっては、トリックを行わないと、const-incorrect関数を呼び出せない場合があります。たとえば、DoTheThing()が渡された文字列の内容を変更しないことがわかっていて、次のコードがあるとします。

_void MyFunction()
{
  std::string msg = "Hello, const correctness";
  DoTheThing(msg.c_str());
}
_

msg.c_str()が_const char*_を返すため、上記のコードはコンパイルされません。このコードをコンパイルするには、次のようにする必要があります。

_void MyFunction()
{
  std::string msg = "Hello, const correctness";
  DoTheThing(msg.begin());
}
_

...さらに悪いことに:

_void MyFunction()
{
  std::string msg = "Hello, const correctness";
  DoTheThing(const_cast<char*>(msg.c_str()));
}
_

どちらも、間違いなく、元のコードよりも「良い」ものではありません。しかし、DoTheThing()はconst-incorrectな方法で記述されているため、コードをその周りに曲げる必要があります。

5
John Dibling

constは、非静的クラスメソッドにアタッチされると、関数がオブジェクトの内部状態を変更しないことをコンパイラーに伝えます。

これは次の2つの点で役立ちます。

  • Constメソッドの内部状態を変更するコードを記述した場合、コンパイラーがエラーをキャッチし、プログラミングエラーを実行時からコンパイル時に移動します。
  • クライアントコードが定数ポインターで非constメソッドを呼び出す場合、コンパイラーはエラーをキャッチし、「変更されないもののチェーン」が維持されるようにします。

通常、すべての非変更非静的クラスメソッドをconstとして宣言します。これにより、呼び出しコードでポインターにconst修飾子を使用できるようになり、間違いを見つけるのに役立ちます。

典型的なC++:クラスメンバー変数を「可変」に宣言してから、それをconstメソッドからevenに変更できます。

4
Ben Supnik

意味は、オブジェクトの状態が変化しないことをconst関数メンバーを呼び出すクライアントに保証することです。したがって、メンバー関数がconstであるとは、関数の呼び出し中にオブジェクトのメンバー変数を変更しないことを意味します。

3
mikelong

これが当てはまる場合は、あらゆる場所で使用する必要があります。メンバー変数を変更または変更する必要がないためです。

うーん、ダメ。 doでインスタンスメソッドを使用してメンバーを変更したい場合があります。たとえば、setメソッドは明らかに変数を設定する必要があるため、どこにでもconstを配置する必要はありません。ただし、オブジェクトの状態が完全に不変である場合は、まずインスタンスをまったく持たない方がよいかどうか(つまり、静的クラス)を検討し、そうでない場合はすべてをconstにします。

2
John Feminella

メンバー変数を変更したくないのは珍しいことですが、それがクラスに必要なものである場合は、すべてのメンバー関数をconstにする必要があります。

ただし、おそらく少なくとも一部のメンバーを変更する必要があります。

class A {
  private: 
    int val;
  public:
    A() : val(0) {}
    void Inc() { val++; }
    int GetVal() const { return val; };
};

ここで、Aの2つのインスタンスを作成するとします。

A a1;
const A a2;

私は言うことができます:

a1.GetVal();
a2.GetVal();

しかし、私は言うことができます:

a1.Inc();

定数オブジェクトの値を変更しようとしています:

a2.Inc();

コンパイルエラーが発生します。

2
anon

メソッドの後に使用されるconstキーワードは、このメソッドが呼び出されたオブジェクトを変更しないことを示します。このようにして、このメソッドはオブジェクトのconstバージョンで呼び出すことができます。

2
Mathieu Pagé