Apa arti dari const
deklarasi seperti ini? Yang const
membingungkan saya.
class foobar
{
public:
operator int () const;
const char* foo() const;
};
Apa arti dari const
deklarasi seperti ini? Yang const
membingungkan saya.
class foobar
{
public:
operator int () const;
const char* foo() const;
};
Jawaban:
Ketika Anda menambahkan const
kata kunci ke suatu metode, this
pointer pada dasarnya akan menjadi pointer ke const
objek, dan karena itu Anda tidak dapat mengubah data anggota. (Kecuali Anda menggunakan mutable
, lebih lanjut tentang itu nanti).
Kata const
kunci adalah bagian dari tanda tangan fungsi yang berarti bahwa Anda dapat menerapkan dua metode serupa, satu yang disebut ketika objek const
, dan satu yang tidak.
#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();
}
Ini akan menampilkan
Foo
Foo const
Dalam metode non-const, Anda dapat mengubah anggota instance, yang tidak dapat Anda lakukan dalam const
versi. Jika Anda mengubah deklarasi metode dalam contoh di atas ke kode di bawah ini Anda akan mendapatkan beberapa kesalahan.
void Foo()
{
counter++; //this works
std::cout << "Foo" << std::endl;
}
void Foo() const
{
counter++; //this will not compile
std::cout << "Foo const" << std::endl;
}
Ini tidak sepenuhnya benar, karena Anda dapat menandai anggota sebagai mutable
dan const
metode kemudian dapat mengubahnya. Ini sebagian besar digunakan untuk penghitung internal dan barang-barang. Solusi untuk itu adalah kode di bawah ini.
#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;
}
yang akan menghasilkan
Foo
Foo const
Foo has been invoked 2 times
Konst tersebut berarti bahwa metode ini berjanji untuk tidak mengubah anggota kelas. Anda dapat mengeksekusi anggota objek yang ditandai, bahkan jika objek itu sendiri ditandai const
:
const foobar fb;
fb.foo();
akan legal.
Lihat Berapa banyak dan mana yang menggunakan "const" di C ++? untuk informasi lebih lanjut.
The const
berarti kualifikasi bahwa metode dapat disebut pada setiap nilai foobar
. Perbedaannya muncul ketika Anda mempertimbangkan untuk memanggil metode non-const pada objek const. Pertimbangkan apakah foobar
tipe Anda memiliki deklarasi metode tambahan berikut:
class foobar {
...
const char* bar();
}
Metode bar()
ini non-const dan hanya dapat diakses dari nilai non-const.
void func1(const foobar& fb1, foobar& fb2) {
const char* v1 = fb1.bar(); // won't compile
const char* v2 = fb2.bar(); // works
}
Gagasan di belakang const
adalah untuk menandai metode yang tidak akan mengubah keadaan internal kelas. Ini adalah konsep yang kuat tetapi sebenarnya tidak dapat diberlakukan di C ++. Ini lebih dari janji daripada jaminan. Dan yang sering rusak dan mudah pecah.
foobar& fbNonConst = const_cast<foobar&>(fb1);
const
ini adalah untuk menandai metode yang tidak akan mengubah keadaan internal kelas". Itu benar-benar yang saya cari.
const
?
Const ini berarti bahwa compiler akan Error jika metode 'with const' mengubah data internal.
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_;
};
Ujian
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
}
Baca ini untuk informasi lebih lanjut
const
fungsi anggota yang tidak menyebutkan bisa berubah tidak lengkap di terbaik.
Jawaban Blair tepat sasaran.
Namun perhatikan bahwa ada mutable
kualifikasi yang dapat ditambahkan ke anggota data kelas. Setiap anggota yang ditandai dapat dimodifikasi dalam suatu const
metode tanpa melanggar const
kontrak.
Anda mungkin ingin menggunakan ini (misalnya) jika Anda ingin objek mengingat berapa kali metode tertentu dipanggil, sementara tidak mempengaruhi keteguhan "logis" dari metode itu.
Arti Fungsi Anggota Konstituen dalam C ++ Pengetahuan Umum: Essential Intermediate Programming memberikan penjelasan yang jelas:
Jenis pointer ini dalam fungsi anggota non-const dari kelas X adalah X * const. Artinya, ini adalah pointer konstan ke X yang tidak konstan (lihat Const Pointers dan Pointers to Const [7, 21]). Karena objek yang dirujuk ini bukan const, ia dapat dimodifikasi. Jenis ini dalam fungsi anggota const dari kelas X adalah const X * const. Yaitu, ini adalah pointer konstan ke X konstan. Karena objek yang dirujuk ini adalah const, ia tidak dapat dimodifikasi. Itulah perbedaan antara fungsi anggota const dan non-const.
Jadi dalam kode Anda:
class foobar
{
public:
operator int () const;
const char* foo() const;
};
Anda dapat menganggapnya sebagai ini:
class foobar
{
public:
operator int (const foobar * const this) const;
const char* foo(const foobar * const this) const;
};
this
tidak const
. Alasan mengapa hal itu tidak dapat dimodifikasi adalah karena ini adalah nilai awal.
ketika Anda menggunakan const
dalam tanda tangan metode (seperti kata const char* foo() const;
Anda:) Anda memberi tahu kompiler bahwa memori yang ditunjuk oleh this
tidak dapat diubah oleh metode ini (yang ada di foo
sini).
Saya ingin menambahkan poin berikut.
Anda juga bisa membuatnya menjadi const &
danconst &&
Begitu,
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
}
Jangan ragu untuk meningkatkan jawabannya. Saya bukan ahli
*this
selalu merupakan lvalue, bahkan jika fungsi anggota adalah rvalue-ref-kualifikasi dan dipanggil pada rvalue. Contoh .
Kata kunci const yang digunakan dengan deklarasi fungsi menetapkan bahwa itu adalah fungsi anggota const dan tidak akan dapat mengubah anggota data objek.
https://isocpp.org/wiki/faq/const-correctness#const-member-fns
Apa itu "
const
fungsi anggota"?Fungsi anggota yang memeriksa (bukan bermutasi) objeknya.
Sebuah
const
fungsi anggota ditunjukkan denganconst
akhiran setelah daftar parameter fungsi anggota ini. Fungsi anggota denganconst
sufiks disebut "fungsi anggota konst" atau "pemeriksa." Fungsi anggota tanpaconst
akhiran disebut "fungsi anggota non-const" atau "mutators."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 }
Upaya untuk menelepon
unchangeable.mutate()
adalah kesalahan yang tertangkap saat kompilasi. Tidak ada ruang runtime atau penalti kecepatan untukconst
, dan Anda tidak perlu menulis kasus uji untuk memeriksanya saat runtime.Trailing
const
padainspect()
fungsi anggota harus digunakan untuk berarti metode tidak akan mengubah keadaan abstrak (terlihat klien) objek. Itu sedikit berbeda dari mengatakan metode tidak akan mengubah "bit mentah" dari struct objek. Kompiler C ++ tidak diizinkan untuk mengambil interpretasi "bitwise" kecuali mereka dapat memecahkan masalah aliasing, yang biasanya tidak dapat diselesaikan (yaitu, alias non-const bisa ada yang dapat mengubah keadaan objek). Wawasan (penting) lain dari masalah aliasing ini: menunjuk ke suatu objek dengan pointer-to-const tidak menjamin bahwa objek tidak akan berubah; itu hanya menjanjikan bahwa objek tidak akan berubah melalui pointer itu .