İnt gibi ilkel tipler tanımlamak için ne kadar ileri gitmek


14

Birçok typedefs ile aşağıdaki gibi C ++ kodu gördüm .

typedefC ++ ilkellerini kullanmanın aksine, bunun gibi pek çok şeyi kullanmanın faydaları nelerdir ? Bu faydaları da sağlayabilecek başka bir yaklaşım var mı?

Sonunda, verilerin tümü bellekte saklanır veya tel üzerinden bit ve bayt olarak iletilir, gerçekten önemli mi?

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;

Denemek ve aynı tür her zaman taşmaları önlemek için belirli bir şey için kullanılır emin olmak için mantıklı görünüyor, ama sık sık "int" yerine hemen hemen her yerde kullanılan kod görüyorum. typedefGenellikle bu olsa biraz benzemekle koduna öne yapar ing:

DoSomething(EscalationLevel escalationLevel) {
    ...
}

Bu da hangi parametrenin gerçekte parametreyi tanımladığını merak etmemi sağlıyor: parametre türü veya parametre adı?


2
IMHO, oldukça anlamsız bir egzersiz gibi gözüküyor, ama eminim ki bazıları da aynı fikirde değil ...
Nim

1
Bu türler değişken isimlerine benziyor.
Kaptan Zürafa

11
Bunun tür güvenli olduğuna dair bir izlenim oluşturduğunu unutmayın, ancak hiç de değil - typedefs yalnızca takma adlar oluşturur, ancak hiçbir şey örneğin a'yı Minutetür olarak bildirilen bir argümana sahip bir işleve geçirmenizi engellemez Second.
Jesper

2
@ Mark: başka bir şekilde bak. Tamsayı türüne karar verirken bir hata yaparsanız veya gelecekte yeni gereksinimler ortaya çıkar ve bu nedenle değiştirmek istiyorsanız, tek bir typedef'i değiştirmek ister misiniz veya bir yılı işleyen her işlev için kodu aramak ister misiniz ve imzasını değiştir? 640k herkes için yeterlidir. Typedef'in buna karşılık gelen dezavantajı, insanların yanlışlıkla veya kasıtlı olarak Yılın tam olarak 16 bit olduğu gerçeğine dayanan kod yazması, daha sonra değişmesi ve kodlarının kırılmasıdır.
Steve Jessop

1
@Steve Jessop: Bunun iyi ya da kötü bir fikir olup olmadığına karar veremem :-) İlk kısım lehte gibi görünüyor, ikincisi karşı. Sanırım artıları ve eksileri var.

Yanıtlar:


13

Bir parametrenin adı ne anlama geldiğini açıklamalıdır - sizin durumunuzda yükselme seviyesi. Tür, değerin nasıl temsil edildiğidir - örneğinizde olduğu gibi typedefs eklenmesi, işlev imzasının bu bölümünü gizler, bu yüzden tavsiye etmem.

Typedefs, şablonlar için yararlıdır veya belirli parametreler için kullanılan türü değiştirmek istiyorsanız, örneğin 32 bit'ten 64 bit platforma geçerken.


Bu genel fikir birliği gibi görünüyor. Yani genellikle "int" e yapışır mısın? Veri aktarımı söz konusu olduğunda bu uygulamada çok verimli olmalıyım, bu yüzden serileştirme sırasında sadece int16_t'ye (veya belirli bir öğe için gereken en büyük gösterim türü) dönüştürülecek bir durum olur mu?

@ Mark: Evet, böyle yapmalısın. Kullanılan veri türlerinin boyutunu ifade etmek için typedefs kullanın, ancak farklı bağlamlarda kullanılanla aynı türü ayırt etmeyin.
Björn Pollex

Teşekkürler - ve sadece açıklığa kavuşturmak için, genellikle kod yerine int yerine int8_t kullanarak rahatsız olmaz .. Ben ana endişe aslında "Kimlik" gibi bir şey aslında bir veritabanı tarafından oluşturulan bir kimlik olduğunu düşünüyorum. Şu anda 32bit ama sonunda 64bit olup olmayacağından henüz emin değilim. Ayrıca, int32_t vs int ne olacak? int genellikle int32_t ile aynıdır, ancak her zaman farklı bir platformda sanırım olmayabilir mi? Ben sadece genel olarak "int" ve gereken "int64_t" sopa gerektiğini düşünüyorum .. teşekkürler :-)

@ Mark: gibi typedefs hakkında önemli olan şey int32_t, farklı platformlarda derlerken doğru olduğundan emin olmak zorunda olmasıdır. Eğer aralığın Identitybir noktada değişmesini bekliyorsanız, değişiklikleri doğrudan etkilenen tüm kodlarda yapmayı tercih ederim. Ama emin değilim, çünkü özel tasarımınız hakkında daha fazla bilgi sahibi olmalıyım. Bunu ayrı bir soru haline getirmek isteyebilirsiniz.
Björn Pollex

17

İlk başta "Neden olmasın" diye düşündüm ama sonra böyle türleri ayırmak için bu kadar uzun boylu olacaksanız, o zaman dili daha iyi kullanın. Takma ad kullanmak yerine, aslında türleri tanımlayın:

class AnalogueValue
{
public:
    // constructors, setters, getters, etc..
private:
    float m_value;
};

Arasında performans farkı yoktur:

typedef float AnalogueValue;
AnalogValue a = 3.0f;
CallSomeFunction (a);

ve:

AnalogValue a (3.0f); // class version
CallSomeFunction (a);

ayrıca parametre doğrulama ve tip güvenliği ekleme avantajlarına da sahipsiniz. Örneğin, ilkel türleri kullanarak parayla ilgilenen kodu düşünün:

float amount = 10.00;
CallSomeFunction(amount);

Yuvarlama sorunlarının yanı sıra, bir şamandıraya dönüştürülebilen her türe de izin verir:

int amount = 10;
CallSomeFunction(amount);

Bu durumda bu büyük bir mesele değildir, ancak örtük dönüşümler, tespit edilmesi zor bir hata kaynağı olabilir. typedefBurada yalnızca bir tür takma adı olduğu için a kullanmak yardımcı olmaz.

Yeni bir tür kullanmak, bir döküm operatörünü kodlamadığınız sürece dolaylı dönüşümlerin olmadığı anlamına gelir; bu, özellikle örtük dönüşümlere izin verdiği için kötü bir fikirdir. Ek verileri de kapsül içine alabilirsiniz:

class Money {
  Decimal amount;
  Currency currency;
};

Money m(Decimal("10.00"), Currency.USD);
CallSomeFunction(m);

Bunu yapmak için kod yazmazsak, başka hiçbir şey bu işleve uymayacaktır. Yanlışlıkla dönüşüm mümkün değildir. Ayrıca çok fazla güçlük çekmeden gerektiğinde daha karmaşık türler yazabiliriz.


1
Bu sınıf yaratımını sizin için yapmak için korkunç bir makro bile yazabilirsiniz. (Hadi, Skizz. İstediğini biliyorsun.)

1
Bunlardan bazıları için, her biri için özel bir sınıf yazmak yerine, tür güvenli bir birim kitaplığı yararlı olabilir ( tuoml.sourceforge.net/html/scalar/scalar.html ).
Steve Jessop

@Chris - Kesinlikle bir makro değil, muhtemelen bir şablon sınıfı. Steve'in işaret ettiği gibi, bu sınıflar zaten yazılmıştır.
kevin cline

4
@Chris: Makro BOOST_STRONG_TYPEDEFaslında denir ;)
Matthieu M.

3

Daha çok C stili koduna benzeyen ilkel türler için typedefs kullanmak.

C ++ 'da, örneğin, EventLevelve için işlevleri aşırı yüklemeye çalıştığınızda ilginç hatalar alırsınız Hour. Bu, ekstra tür adlarını oldukça işe yaramaz hale getirir.


2

Biz (şirketimizde) C ++ 'da çok şey yapıyoruz. Kodun anlaşılmasına ve korunmasına yardımcı olur. İnsanları ekipler arasında hareket ettirirken veya yeniden düzenleme yaparken iyidir. Misal:

typedef float Price;
typedef int64_t JavaTimestmap;

void f(JavaTimestamp begin, JavaTimestamp end, Price income);

Temsil türünden boyut adına typedef oluşturmanın iyi bir uygulama olduğuna inanıyoruz. Bu yeni ad bir yazılımda genel bir rolü temsil eder . Parametrenin adı yerel bir roldür . Gibi User sender, User receiver. Bazı yerlerde gereksiz olabilir void register(User user), ama bunun bir sorun olduğunu düşünmüyorum.

Daha sonra float, rezervasyonun özel yuvarlama kuralları nedeniyle fiyatları temsil etmek için en iyi olmayan bir fikir olabilir , bu yüzden biri BCDFloat(ikili kodlu ondalık) türünü indirir veya uygular ve typedef'i değiştirir. Hiçbir arama ve gelen işleri yerine floatkadar BCDFloatkodunuzda muhtemelen çok daha fazla yüzer olduğu gerçeği ile sertleştirilmiş edileceği.

Gümüş bir kurşun değildir ve kendi uyarıları vardır, ancak kullanmamaktan çok daha iyi olduğunu düşünüyoruz.


Veya Mathieu M.'nin Skizz'in postunda önerdiği gibi BOOST_STRONG_TYPEDEF(float, Price), biri gidebilir , ancak ortalama bir projede bu kadar ileri gitmem. Ya da belki de isterdim. Üzerinde uyumak zorundayım. :-)
Notinlist

1

typedeftemelde bir için bir takma ad vermenizi sağlar type.
Uzun type namesve tekrar yazmayı önleme typeve takma adın amacını veya amacını gösterdiği daha kolay okunabilir hale getirme esnekliği sağlar type.

typedefProjenizde daha fazla okunabilir isme sahip olmak istiyorsanız daha çok tercih edilir .
Genellikle, typedefyazılmaları olağandışı uzun olmadıkça, ilkel türlerde kullanmaktan kaçınırım . Parametre adlarımı daha gösterge niteliğinde tutuyorum.


0

Asla böyle bir şey yapmam. Hepsinin aynı boyuta sahip olduğundan emin olmak bir şeydir - ancak bunlara sadece integral türler olarak başvurmanız gerekir.


0

Bu gibi typedefs kullanmak, onları kullanan herkes rüzgarın altında yatan temsiller hakkında hiçbir şey bilmesine gerek olmadığı sürece iyidir . Örneğin, bir PacketLengthnesneyi printfveya nesnelerine iletmek istiyorsanız scanf, doğru dönüşüm belirtecini seçebilmeniz için gerçek türünü bilmeniz gerekir. Bu gibi durumlarda, typedef karşılığında hiçbir şey satın almadan sadece bir şaşkınlık seviyesi ekler; siz de nesneyi yeni tanımlamış olabilirsiniz int32_t.

Her bir türe özgü (izin verilen aralıklar veya değerler gibi) anlambilim uygulamanız gerekiyorsa, yalnızca bir typedef oluşturmak yerine, soyut bir veri türü ve bu tür üzerinde çalışacak işlevler oluşturmaktan daha iyi olursunuz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.