berasal dari latar belakang terutama python Saya agak kesulitan bekerja dengan tipe C ++.
Saya mencoba menginisialisasi variabel kelas melalui salah satu dari beberapa konstruktor kelebihan beban yang menggunakan berbagai jenis sebagai parameter. Saya telah membaca bahwa menggunakan auto
kata kunci dapat digunakan untuk deklarasi otomatis suatu variabel, namun dalam kasus saya ini tidak akan diinisialisasi sampai konstruktor dipilih. Namun kompiler tidak senang tidak menginisialisasi value
.
class Token {
public:
auto value;
Token(int ivalue) {
value = ivalue;
}
Token(float fvalue) {
value = fvalue;
}
Token(std::string svalue) {
value = svalue;
}
void printValue() {
std::cout << "The token value is: " << value << std::endl;
}
};
Dalam python ini mungkin terlihat seperti:
class Token():
def __init__(self, value):
self.value = value
def printValue(self):
print("The token value is: %s" % self.value)
Apa cara yang benar untuk menggunakan auto
kata kunci dalam skenario ini? Haruskah saya menggunakan pendekatan yang berbeda sama sekali?
auto
anggota kelas sama sekali? Pertanyaan yang relevan tetapi kedaluwarsa: Apakah mungkin untuk memiliki variabel anggota "otomatis"?Jawaban:
Tidak ada yang namanya "variabel tipe tidak dikenal" di C ++.
variabel yang dideduksi otomatis memiliki tipe yang dideduksi dari initialiser. Jika tidak ada penginisialisasi, maka Anda tidak dapat menggunakan otomatis. otomatis tidak dapat digunakan untuk variabel anggota yang tidak statis. Satu instance kelas tidak dapat memiliki anggota yang diketik berbeda dari instance lain.
Tidak ada cara menggunakan kata kunci otomatis dalam skenario ini.
Mungkin. Sepertinya Anda mencoba menerapkan
std::variant
. Jika Anda memerlukan variabel untuk menyimpan salah satu tipe X, itulah yang harus Anda gunakan.Namun, Anda mungkin mencoba meniru pengetikan dinamis dalam C ++. Meskipun mungkin sudah tidak asing bagi Anda karena pengalaman dengan Python, dalam banyak kasus itu bukan pendekatan yang ideal. Misalnya, dalam program contoh khusus ini, semua yang Anda lakukan dengan variabel anggota adalah mencetaknya. Jadi akan lebih mudah untuk menyimpan string di setiap case. Pendekatan lain adalah polimorfisme statis seperti yang ditunjukkan oleh Rhathin atau polimorfisme dinamis gaya OOP seperti yang ditunjukkan oleh Fire Lancer.
sumber
union
adalah mekanisme tingkat rendah yang rawan kesalahan.variant
mungkin menggunakannya secara internal dan membuat penggunaannya lebih aman.variant
tidak digunakanunion
. Alternatifnya, menggunakan memori mentah dan penempatan baru, tidak dapat digunakan dalamconstexpr
konstruktor.C ++ adalah bahasa yang diketik secara statis , artinya semua tipe variabel ditentukan sebelum runtime. Oleh karena itu,
auto
kata kunci bukanlah sesuatu sepertivar
kata kunci dalam javascript, yang merupakan bahasa yang diketik secara dinamis.auto
kata kunci biasanya digunakan untuk menentukan jenis yang tidak perlu rumit.Apa yang Anda cari mungkin dilakukan dengan menggunakan kelas template C ++, yang memungkinkan pembuatan beberapa versi kelas yang menggunakan tipe berbeda.
Kode ini mungkin jawaban yang Anda cari.
Kode ini akan dikompilasi jika beberapa kondisi terpenuhi, seperti fungsi
operator<<
harus didefinisikan untuk std :: ostream & dan ketik T.sumber
Pendekatan yang berbeda, dari apa yang diusulkan orang lain, adalah menggunakan templat. Berikut ini sebuah contoh:
Maka Anda dapat menggunakan kelas Anda seperti ini:
sumber
Anda bisa menggunakan
std::variant
tipe tersebut. Kode di bawah ini menunjukkan satu cara (tapi agak canggung, saya harus akui):Akan jauh lebih baik jika
std::get<0>(value)
bisa ditulis sebagaistd::get<value.index()>(value)
tetapi, sayangnya, "x" di<x>
harus menjadi ekspresi konstan waktu kompilasi.sumber
std::visit
daripadaswitch
.auto
harus dapat dikurangkan ke jenis tertentu, itu tidak menyediakan mengetik dinamis runtime.Jika pada saat menyatakan
Token
Anda tahu semua tipe yang mungkin dapat Anda gunakan,std::variant<Type1, Type2, Type3>
dll. Ini mirip dengan memiliki "tipe enum" dan "gabungan". Itu memastikan konstruktor dan destruktor yang tepat dipanggil.Alternatifnya adalah membuat
Token
subtipe yang berbeda untuk setiap kasus (mungkin menggunakan templat) dengan metode virtual yang sesuai.sumber
Solusi di bawah ini serupa dalam semangat dengan yang ada di jawaban Fire Lancer. Perbedaan utamanya adalah mengikuti komentar yang mungkin menggunakan templat , dan karenanya menghilangkan kebutuhan untuk secara eksplisit membuat turunan instance dari antarmuka.
Token
bukan kelas antarmuka itu sendiri. Alih-alih, ia mendefinisikan antarmuka sebagai kelas dalam, dan kelas templat dalam untuk mengotomatiskan definisi kelas turunan.Definisi itu tampak terlalu rumit. Namun,
Token::Base
mendefinisikan antarmuka, danToken::Impl<>
berasal dari antarmuka. Kelas-kelas dalam ini sepenuhnya tersembunyi bagi penggunaToken
. Penggunaannya akan terlihat seperti:Juga, solusi di bawah ini mengilustrasikan bagaimana seseorang dapat mengimplementasikan operator konversi untuk menetapkan
Token
instance ke variabel reguler. Ini bergantung padadynamic_cast
, dan akan melemparkan pengecualian jika para pemain tidak valid.Definisi di
Token
bawah ini.Cobalah online!
sumber