Saya telah melihat kode C ++ seperti berikut dengan banyak typedef
s.
Apa manfaat menggunakan banyak typedef
s seperti ini dibandingkan dengan menggunakan primitif C ++? Apakah ada pendekatan lain yang mungkin juga mencapai manfaat itu?
Pada akhirnya, semua data disimpan dalam memori atau dikirim melalui kabel sebagai bit dan byte, apakah itu penting?
types.h:
typedef int16_t Version;
typedef int32_t PacketLength;
typedef int32_t Identity;
typedef int32_t CabinetNumber;
typedef int64_t Time64;
typedef int64_t RFID;
typedef int64_t NetworkAddress;
typedef int64_t PathfinderAddress;
typedef int16_t PathfinderPan;
typedef int16_t PathfinderChannel;
typedef int64_t HandsetSerialNumber;
typedef int16_t PinNumber;
typedef int16_t LoggingInterval;
typedef int16_t DelayMinutes;
typedef int16_t ReminderDelayMinutes;
typedef int16_t EscalationDelayMinutes;
typedef float CalibrationOffset;
typedef float AnalogValue;
typedef int8_t PathfinderEtrx;
typedef int8_t DampingFactor;
typedef int8_t RankNumber;
typedef int8_t SlavePort;
typedef int8_t EventLevel;
typedef int8_t Percent;
typedef int8_t SensorNumber;
typedef int8_t RoleCode;
typedef int8_t Hour;
typedef int8_t Minute;
typedef int8_t Second;
typedef int8_t Day;
typedef int8_t Month;
typedef int16_t Year;
typedef int8_t EscalationLevel;
Tampaknya logis untuk mencoba dan memastikan tipe yang sama selalu digunakan untuk hal tertentu untuk menghindari kelebihan, tetapi saya sering melihat kode di mana "int" baru saja digunakan di mana-mana. The typedef
ing sering tidak menyebabkan kode yang terlihat sedikit seperti ini meskipun:
DoSomething(EscalationLevel escalationLevel) {
...
}
Yang kemudian membuat saya bertanya-tanya token mana yang sebenarnya menggambarkan parameter: tipe parameter atau nama parameter?
sumber
Minute
ke fungsi yang argumennya dideklarasikan sebagai tipeSecond
.Jawaban:
Nama parameter harus menggambarkan apa artinya - dalam kasus Anda tingkat eskalasi. Jenisnya adalah bagaimana nilainya diwakili - menambahkan typedefs seperti dalam contoh Anda mengaburkan bagian dari tanda tangan fungsi ini, jadi saya tidak akan merekomendasikannya.
Typedef berguna untuk templat, atau jika Anda ingin mengubah jenis yang digunakan untuk parameter tertentu, misalnya ketika bermigrasi dari platform 32bit ke 64bit.
sumber
int32_t
adalah Anda harus memastikan semuanya benar ketika mengkompilasi pada platform yang berbeda. Jika Anda mengharapkan rentangIdentity
untuk berubah di beberapa titik, saya pikir saya lebih suka untuk membuat perubahan secara langsung di semua kode yang terpengaruh. Tetapi saya tidak yakin, karena saya perlu tahu lebih banyak tentang desain spesifik Anda. Anda mungkin ingin menjadikan itu pertanyaan terpisah.Pada awalnya saya berpikir "Mengapa tidak" tetapi kemudian terpikir oleh saya bahwa jika Anda akan berusaha keras untuk memisahkan jenis-jenis seperti itu, maka manfaatkanlah bahasa dengan lebih baik. Alih-alih menggunakan alias, sebenarnya tentukan jenis:
Tidak ada perbedaan kinerja antara:
dan:
dan Anda juga memiliki kelebihan menambahkan validasi parameter dan keamanan tipe. Misalnya, pertimbangkan kode yang berhubungan dengan uang menggunakan tipe primitif:
Selain masalah pembulatan, ini juga memungkinkan semua jenis yang dapat dikonversi menjadi pelampung:
Dalam hal ini ini bukan masalah besar, tetapi konversi implisit dapat menjadi sumber bug yang sulit untuk dijabarkan. Menggunakan a
typedef
tidak membantu di sini, karena mereka hanyalah tipe alias.Menggunakan tipe baru sepenuhnya berarti tidak ada konversi implisit kecuali jika Anda memberi kode pada operator casting, yang merupakan ide buruk secara khusus karena memungkinkan konversi implisit. Anda juga dapat merangkum data tambahan:
Tidak ada hal lain yang cocok dengan fungsi itu kecuali kita menulis kode untuk mewujudkannya. Konversi yang tidak disengaja tidak mungkin. Kita juga dapat menulis tipe yang lebih kompleks sesuai kebutuhan tanpa banyak kesulitan.
sumber
BOOST_STRONG_TYPEDEF
sebenarnya disebut ;)Menggunakan typedef untuk tipe primitif seperti itu lebih mirip kode gaya C.
Di C ++ Anda akan mendapatkan kesalahan yang menarik segera setelah Anda mencoba untuk membebani fungsi untuk, katakanlah,
EventLevel
danHour
. Itu membuat nama tipe ekstra tidak berguna.sumber
Kami (di perusahaan kami) banyak melakukannya di C ++. Ini membantu memahami dan memelihara kode. Yang bagus saat memindahkan orang antar tim atau melakukan refactoring. Contoh:
Kami percaya ini adalah praktik yang baik untuk membuat typedef ke nama dimensi dari tipe representasi. Nama baru ini mewakili peran umum dalam suatu perangkat lunak. Nama parameter adalah peran lokal . Seperti di
User sender, User receiver
. Di beberapa tempat itu bisa jadi berlebihan, sepertivoid register(User user)
, tapi saya tidak menganggapnya sebagai masalah.Kemudian orang mungkin memiliki gagasan yang
float
bukan yang terbaik untuk mewakili harga karena aturan pembulatan khusus pemesanan, jadi seseorang mengunduh atau mengimplementasikan tipeBCDFloat
(desimal berkode biner) dan mengubah typedef. Tidak ada pencarian dan mengganti bekerja darifloat
keBCDFloat
mana akan mengeras oleh fakta bahwa ada lebih mungkin banyak mengapung dalam kode Anda.Ini bukan peluru perak dan memiliki peringatan sendiri, tetapi kami pikir itu jauh lebih baik menggunakannya daripada tidak.
sumber
BOOST_STRONG_TYPEDEF(float, Price)
, tapi saya tidak akan sejauh itu pada proyek rata-rata. Atau mungkin saya akan melakukannya. Saya harus tidur di situ. :-)typedef
pada dasarnya memungkinkan Anda untuk memberikan alias untuktype
.Ini memberi Anda fleksibilitas untuk menghindari mengetik
type names
lagi dan lagi dan membuat Andatype
lebih mudah dibaca dimana nama alias menunjukkan maksud atau tujuan daritype
.Ini lebih merupakan masalah pilihan jika Anda ingin memiliki lebih banyak nama yang dapat dibaca melalui
typedef
proyek Anda.Biasanya, saya menghindari penggunaan
typedef
pada tipe primitif, kecuali mereka terlalu panjang untuk diketik. Saya menjaga agar nama parameter saya lebih bersifat indikatif.sumber
Saya tidak akan pernah melakukan hal seperti ini. Memastikan mereka semua memiliki ukuran yang sama adalah satu hal - tetapi Anda hanya perlu menyebutnya sebagai tipe yang tidak terpisahkan.
sumber
Menggunakan typedef seperti ini tidak masalah selama siapa pun yang menggunakannya tidak perlu tahu apa-apa tentang representasi yang mendasarinya . Misalnya, jika Anda ingin meneruskan
PacketLength
objek ke salah satuprintf
atauscanf
, Anda harus tahu jenis sebenarnya sehingga Anda dapat memilih specifier konversi yang tepat. Dalam kasus seperti itu, typedef hanya menambah tingkat kebingungan tanpa membeli imbalan apa pun; Anda mungkin baru saja mendefinisikan objek sebagaiint32_t
.Jika Anda perlu menerapkan semantik khusus untuk setiap jenis (seperti rentang atau nilai yang diizinkan), maka Anda lebih baik membuat tipe data abstrak dan fungsi untuk beroperasi pada tipe itu, daripada hanya membuat typedef.
sumber