このような宣言におけるconst
の意味は何ですか? const
は私を混乱させる。
class foobar
{
public:
operator int () const;
const char* foo() const;
};
const
キーワードをメソッドに追加すると、this
ポインタは基本的にconst
オブジェクトへのポインタになるため、メンバーデータを変更することはできません。 (あなたがmutable
を使わない限り、後でもっと詳しく)。
const
キーワードはfunctionsシグネチャの一部です。つまり、オブジェクトがconst
のときに呼び出されるメソッドとそうでないメソッドの2つを実装できます。
#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++;
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 << "The MyClass instance has been invoked " << ccc.GetInvocations() << " times" << endl;
}
どちらが出力されます
Foo
Foo const
The MyClass instance has been invoked 2 times
Constは、メソッドがクラスのメンバを変更しないことを約束することを意味します。オブジェクト自体がconst
とマークされていても、そのようにマークされているオブジェクトのメンバーを実行することができます。
const foobar fb;
fb.foo();
合法です。
を参照してください。C++でのconstの使用方法はいくつですか。 詳細については。
const
修飾子は、メソッドがfoobar
の任意の値で呼び出すことができることを意味します。違いは、constオブジェクトに対してnon-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は、 '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
}
詳細については this を読んでください。
ブレアの答えは目の前にあります。
ただし、クラスのデータメンバに追加できるmutable
修飾子があります。 canとマークされたメンバーは、const
規約に違反することなくconst
メソッドで変更できます。
特定のメソッドが呼び出された回数をオブジェクトに記憶させ、そのメソッドの「論理的」な制約には影響を与えない場合は、これを使用することをお勧めします。
定数メンバ関数の意味 in C++共通知識:基本的な中級プログラミング は明確な説明を与える
クラスXの非constメンバー関数内のthisポインターの型はX * constです。つまり、これは非定数Xへの定数ポインタです(Const PointersおよびConstへのポインタ[7、21]を参照)。これが参照するオブジェクトはconstではないため、変更することができます。クラスXのconstメンバー関数内のthisの型は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;
};
メソッドシグネチャに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
}
答えを改善すること自由に感じなさい。私は専門家ではありません
関数宣言で使用されるconstキーワードは、それがconstメンバー関数であり、それが変更不可のデータメンバーであることを指定しますオブジェクト。