Saya hanya salah melakukan sesuatu seperti ini di C ++, dan berhasil. Mengapa saya bisa melakukan ini?
int main(int argc, char** argv) {
struct MyStruct
{
int somevalue;
};
MyStruct s;
s.somevalue = 5;
}
Sekarang setelah melakukan ini, saya ingat pernah membaca tentang trik ini di suatu tempat, dahulu kala, sebagai semacam alat pemrograman fungsional orang miskin untuk C ++, tetapi saya tidak dapat mengingat mengapa ini valid, atau di mana saya membacanya.
Kami menerima jawaban untuk kedua pertanyaan tersebut!
Catatan: Meskipun ketika menulis pertanyaan saya tidak mendapatkan referensi apa pun untuk pertanyaan ini , bilah samping saat ini menunjukkannya jadi saya akan meletakkannya di sini untuk referensi, bagaimanapun pertanyaannya berbeda tetapi mungkin berguna.
c++
data-structures
functional-programming
Robert Gould
sumber
sumber
Jawaban:
[EDIT 18/4/2013]: Untungnya, batasan yang disebutkan di bawah ini telah dicabut di C ++ 11, jadi kelas yang ditentukan secara lokal berguna! Terima kasih kepada pemberi komentar bamboon.
Kemampuan untuk mendefinisikan kelas secara lokal akan membuat pembuatan
operator()()
fungsi kustom (kelas dengan , misalnya fungsi perbandingan untuk meneruskan kestd::sort()
atau "badan loop" yang akan digunakanstd::for_each()
) jauh lebih nyaman.Sayangnya, C ++ melarang penggunaan kelas yang ditentukan secara lokal dengan template , karena tidak memiliki keterkaitan. Karena sebagian besar aplikasi dari functor melibatkan jenis template yang memiliki template pada jenis functor, kelas yang ditentukan secara lokal tidak dapat digunakan untuk ini - Anda harus menentukannya di luar fungsi. :(
[EDIT 1/11/2009]
Kutipan relevan dari standar adalah:
sumber
Salah satu aplikasi kelas C ++ yang ditentukan secara lokal ada dalam pola desain Pabrik :
// In some header class Base { public: virtual ~Base() {} virtual void DoStuff() = 0; }; Base* CreateBase( const Param& ); // in some .cpp file Base* CreateBase( const Params& p ) { struct Impl: Base { virtual void DoStuff() { ... } }; ... return new Impl; }
Meskipun Anda dapat melakukan hal yang sama dengan namespace anonim.
sumber
Ini sebenarnya sangat berguna untuk melakukan beberapa pekerjaan keamanan-pengecualian berbasis tumpukan. Atau pembersihan umum dari fungsi dengan beberapa titik balik. Ini sering disebut idiom RAII (akuisisi sumber daya adalah inisialisasi).
void function() { struct Cleaner { Cleaner() { // do some initialization code in here // maybe start some transaction, or acquire a mutex or something } ~Cleaner() { // do the associated cleanup // (commit your transaction, release your mutex, etc.) } }; Cleaner cleaner; // Now do something really dangerous // But you know that even in the case of an uncaught exception, // ~Cleaner will be called. // Or alternatively, write some ill-advised code with multiple return points here. // No matter where you return from the function ~Cleaner will be called. }
sumber
Cleaner cleaner();
Saya pikir ini akan menjadi deklarasi fungsi daripada definisi objek.Cleaner cleaner;
atauCleaner cleaner{};
.Nah, pada dasarnya, kenapa tidak? A
struct
in C (kembali ke awal waktu) hanyalah cara untuk mendeklarasikan struktur record. Jika Anda menginginkannya, mengapa tidak dapat mendeklarasikannya di mana Anda akan mendeklarasikan variabel sederhana?Setelah Anda melakukannya, ingatlah bahwa tujuan C ++ adalah agar kompatibel dengan C jika memungkinkan. Jadi itu bertahan.
sumber
Ini disebutkan di, misalnya, bagian "7.8: Kelas lokal: kelas di dalam fungsi" dari http://www.icce.rug.nl/documents/cplusplus/cplusplus07.html yang menyebutnya sebagai "kelas lokal" dan mengatakannya " bisa sangat berguna dalam aplikasi lanjutan yang melibatkan pewarisan atau templat ".
sumber
Ini untuk membuat array objek yang diinisialisasi dengan benar.
Saya memiliki kelas C yang tidak memiliki konstruktor default. Saya ingin array objek kelas C. Saya mencari tahu bagaimana saya ingin objek tersebut diinisialisasi, kemudian mendapatkan kelas D dari C dengan metode statis yang memberikan argumen untuk C dalam konstruktor default D:
#include <iostream> using namespace std; class C { public: C(int x) : mData(x) {} int method() { return mData; } // ... private: int mData; }; void f() { // Here I am in f. I need an array of 50 C objects starting with C(22) class D : public C { public: D() : C(D::clicker()) {} private: // I want my C objects to be initialized with consecutive // integers, starting at 22. static int clicker() { static int current = 22; return current++; } }; D array[50] ; // Now I will display the object in position 11 to verify it got initialized // with the right value. cout << "This should be 33: --> " << array[11].method() << endl; cout << "sizodf(C): " << sizeof(C) << endl; cout << "sizeof(D): " << sizeof(D) << endl; return; } int main(int, char **) { f(); return 0; }
Demi kesederhanaan, contoh ini menggunakan konstruktor non-default sepele dan kasus di mana nilainya diketahui pada waktu kompilasi. Sangat mudah untuk memperluas teknik ini ke kasus di mana Anda ingin array objek diinisialisasi dengan nilai yang hanya diketahui pada waktu proses.
sumber
D*
parameter) maka ini akan diam-diam rusak jika D sebenarnya lebih besar dari C . (Saya pikir ...)