Entah bagaimana saya terkejut bahwa kode berikut mengkompilasi dan menjalankan (vc2012 & gcc4.7.2)
class Foo {
struct Bar { int i; };
public:
Bar Baz() { return Bar(); }
};
int main() {
Foo f;
// Foo::Bar b = f.Baz(); // error
auto b = f.Baz(); // ok
std::cout << b.i;
}
Apakah benar kode ini mengkompilasi dengan baik? Dan mengapa itu benar? Mengapa saya bisa menggunakan auto
tipe pribadi, sementara saya tidak bisa menggunakan namanya (seperti yang diharapkan)?
c++
c++11
auto
private-members
hansmaad
sumber
sumber
f.Baz().i
juga OK, seperti apa adanyastd::cout << typeid(f.Baz()).name()
. Kode di luar kelas dapat "melihat" jenis yang dikembalikan olehBaz()
jika Anda dapat memperolehnya, Anda tidak dapat menyebutkannya.private
ada kemudahan untuk menggambarkan API dengan cara yang dapat dikompilasi oleh kompiler. Itu tidak dimaksudkan untuk mencegah akses ke tipeBar
oleh penggunaFoo
, jadi itu tidak menghalangiFoo
dengan cara apapun dari menawarkan akses itu dengan mengembalikan instanceBar
.#include <iostream>
. ;-)Jawaban:
Aturan untuk
auto
adalah, untuk sebagian besar, sama dengan pengurangan jenis template. Contoh yang diposting berfungsi karena alasan yang sama Anda bisa meneruskan objek tipe pribadi ke fungsi templat:Dan mengapa kita bisa meneruskan objek tipe pribadi ke fungsi templat, Anda bertanya? Karena hanya nama jenisnya yang tidak bisa diakses. Jenisnya sendiri masih dapat digunakan, itulah mengapa Anda dapat mengembalikannya ke kode klien sama sekali.
sumber
public: typedef Bar return_type_from_Baz;
ke kelasFoo
dalam pertanyaan. Sekarang tipe dapat diidentifikasi dengan nama publik, meskipun didefinisikan di bagian pribadi kelas.private: typedef Bar return_type_from_Baz;
keFoo
, sebagai ditunjukkan .typedef
Pengidentifikasi lupa untuk mengakses specifier, publik dan pribadi.Bar
atauSomeDeducedType
? Bukannya saya bisa menggunakannya untuk mendapatkan anggota pribadiclass Foo
atau apa pun.Kontrol akses diterapkan ke nama . Bandingkan dengan contoh ini dari standar:
sumber
Pertanyaan ini telah dijawab dengan sangat baik oleh chill dan R. Martinho Fernandes.
Saya tidak bisa melewatkan kesempatan untuk menjawab pertanyaan dengan analogi Harry Potter:
https://ideone.com/I5q7gw
Terima kasih kepada Quentin karena mengingatkanku akan celah Harry.
sumber
friend class Harry;
hilang di sana?friend class Dumbledore;
;)Wizard::LordVoldemort;
C ++ modern. Sebaliknya, dia memanggilusing Wizard::LordVoldemort;
. (Jujur saja, rasanya tidak wajar menggunakan Voldemort. ;-)Untuk menambah jawaban (baik) lainnya, berikut adalah contoh dari C ++ 98 yang menggambarkan bahwa masalah sebenarnya tidak ada hubungannya
auto
sama sekaliMenggunakan tipe pribadi tidak dilarang, itu hanya penamaan tipe. Membuat temporer yang tidak bernama dari jenis itu boleh saja, misalnya, di semua versi C ++.
sumber