回答:
const
メソッドにキーワードを追加すると、this
ポインターは基本的にconst
オブジェクトへのポインターになるため、メンバーデータを変更することはできません。(を使用しない限りmutable
、後で詳しく説明します)。
const
キーワードは2つの類似した方法で、オブジェクトがあるときに呼び出される1実装できることを意味機能の署名の一部でありconst
、かつではないものを。
#include <iostream>
class MyClass
{
private:
int counter;
public:
void Foo()
{
std::cout << "Foo" << std::endl;
}
void Foo() const
{
std::cout << "Foo const" << std::endl;
}
};
int main()
{
MyClass cc;
const MyClass& ccc = cc;
cc.Foo();
ccc.Foo();
}
これは出力されます
Foo
Foo const
non-constメソッドでは、インスタンスメンバーを変更できますが、const
バージョンではできません。上記の例のメソッド宣言を以下のコードに変更すると、いくつかのエラーが発生します。
void Foo()
{
counter++; //this works
std::cout << "Foo" << std::endl;
}
void Foo() const
{
counter++; //this will not compile
std::cout << "Foo const" << std::endl;
}
メンバーをとしてマークしmutable
、const
メソッドがメンバーを変更できるため、これは完全には当てはまりません。主に内部カウンターなどに使用されます。その解決策は以下のコードです。
#include <iostream>
class MyClass
{
private:
mutable int counter;
public:
MyClass() : counter(0) {}
void Foo()
{
counter++;
std::cout << "Foo" << std::endl;
}
void Foo() const
{
counter++; // This works because counter is `mutable`
std::cout << "Foo const" << std::endl;
}
int GetInvocations() const
{
return counter;
}
};
int main(void)
{
MyClass cc;
const MyClass& ccc = cc;
cc.Foo();
ccc.Foo();
std::cout << "Foo has been invoked " << ccc.GetInvocations() << " times" << std::endl;
}
出力される
Foo
Foo const
Foo has been invoked 2 times
constは、メソッドがクラスのメンバーを変更しないことを約束することを意味します。オブジェクト自体がマークされていても、そのようにマークされたオブジェクトのメンバーを実行できますconst
。
const foobar fb;
fb.foo();
合法です。
C ++での「const」の使用方法と使用方法を参照してください。詳細については。
const
方法は、任意の値に呼び出すことができるという修飾子の手段foobar
。違いは、constオブジェクトで非constメソッドを呼び出すことを検討した場合です。foobar
型に次の追加のメソッド宣言があるかどうかを検討してください。
class foobar {
...
const char* bar();
}
このメソッドbar()
は非constであり、非const値からのみアクセスできます。
void func1(const foobar& fb1, foobar& fb2) {
const char* v1 = fb1.bar(); // won't compile
const char* v2 = fb2.bar(); // works
}
const
ただし、背後にある考え方は、クラスの内部状態を変更しないメソッドをマークすることです。これは強力な概念ですが、C ++では実際には強制できません。それは保証というよりも約束です。そして、しばしば壊れて、壊れやすいもの。
foobar& fbNonConst = const_cast<foobar&>(fb1);
const
しかし、背後にある考えは、クラスの内部状態を変更しないメソッドをマークすることです」に感謝します。それが本当に私が探していたものです。
const
か?
これらのconstは、「with const」メソッドが内部データを変更するとコンパイラーがエラーになることを意味します。
class A
{
public:
A():member_()
{
}
int hashGetter() const
{
state_ = 1;
return member_;
}
int goodGetter() const
{
return member_;
}
int getter() const
{
//member_ = 2; // error
return member_;
}
int badGetter()
{
return member_;
}
private:
mutable int state_;
int member_;
};
テスト
int main()
{
const A a1;
a1.badGetter(); // doesn't work
a1.goodGetter(); // works
a1.hashGetter(); // works
A a2;
a2.badGetter(); // works
a2.goodGetter(); // works
a2.hashGetter(); // works
}
詳細については、こちらをお読みください
constメンバ関数の意味でのC ++共通知識:エッセンシャル中級プログラミングは明確な説明を与えます:
クラスXの非constメンバー関数のthisポインターの型はX * constです。つまり、それは非定数Xへの定数ポインターです(ConstポインターとConstへのポインター[7、21]を参照)。これが参照するオブジェクトはconstではないため、変更できます。クラスXのconstメンバー関数でのこの型は、const X * constです。つまり、定数Xへの定数ポインターです。これが参照するオブジェクトはconstであるため、変更できません。それがconstメンバー関数とnon-constメンバー関数の違いです。
だからあなたのコードで:
class foobar
{
public:
operator int () const;
const char* foo() const;
};
あなたはそれを次のように考えることができます:
class foobar
{
public:
operator int (const foobar * const this) const;
const char* foo(const foobar * const this) const;
};
this
はありませんconst
。変更できないのは、それが適切な値であるためです。
const
メソッドシグネチャで使用する場合(前述のようにconst char* foo() const;
)はthis
、このメソッド(foo
ここにあります)によってポイントされたメモリは変更できないことをコンパイラに通知しています。
以下の点を付け加えたいと思います。
あなたも作ることができ 、それconst &
とconst &&
そう、
struct s{
void val1() const {
// *this is const here. Hence this function cannot modify any member of *this
}
void val2() const & {
// *this is const& here
}
void val3() const && {
// The object calling this function should be const rvalue only.
}
void val4() && {
// The object calling this function should be rvalue reference only.
}
};
int main(){
s a;
a.val1(); //okay
a.val2(); //okay
// a.val3() not okay, a is not rvalue will be okay if called like
std::move(a).val3(); // okay, move makes it a rvalue
}
答えを自由に改善してください。私は専門家ではありません
*this
メンバー関数が右辺値参照修飾されており、右辺値で呼び出された場合でも、常に左辺値です。例。
constキーワードは、それがあることを関数宣言の指定に使用さconstメンバ関数と、なり変更することはできませんオブジェクトのデータメンバを。
https://isocpp.org/wiki/faq/const-correctness#const-member-fns
「とは
const
メンバー関数」ですか?オブジェクトを検査する(変更するのではなく)メンバー関数。
const
メンバ関数は、で示されるconst
だけのメンバ関数のパラメータリストの後に接尾辞。const
接尾辞付きのメンバー関数は、「constメンバー関数」または「インスペクター」と呼ばれます。const
サフィックスのないメンバー関数は、「非constメンバー関数」または「ミューテーター」と呼ばれます。class Fred { public: void inspect() const; // This member promises NOT to change *this void mutate(); // This member function might change *this }; void userCode(Fred& changeable, const Fred& unchangeable) { changeable.inspect(); // Okay: doesn't change a changeable object changeable.mutate(); // Okay: changes a changeable object unchangeable.inspect(); // Okay: doesn't change an unchangeable object unchangeable.mutate(); // ERROR: attempt to change unchangeable object }
呼び出しの試み
unchangeable.mutate()
は、コンパイル時にキャッチされたエラーです。には実行時のスペースや速度のペナルティはなく、実行時const
にチェックするためのテストケースを作成する必要はありません。末尾
const
のinspect()
メンバ関数は、オブジェクトの変更されません方法を意味するために使用されるべき抽象(クライアントから見える)状態。これは、メソッドがオブジェクトの構造体の「生のビット」を変更しないと言うのとは少し異なります。C ++コンパイラーは、通常は解決できないエイリアシングの問題(つまり、オブジェクトの状態を変更する可能性のある非constエイリアスが存在する可能性がある)を解決できない限り、「ビット単位」の解釈を行うことはできません。このエイリアスの問題からの別の(重要な)洞察:constへのポインターでオブジェクトを指すことは、オブジェクトが変更されないことを保証しません。オブジェクトがそのポインタを介して変更されないことを約束するだけです。