像int这样的typedef原始类型有多远


14

我已经看到了C ++代码,例如以下带有许多typedefs的代码。

typedef与使用C ++原语相比,使用许多此类有什么好处?是否有另一种方法也可以实现这些好处?

最后,数据全部以位和字节的形式存储在内存中或通过导线传输,这真的重要吗?

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;

尝试确保始终将同一类型用于特定事物以避免溢出似乎是合乎逻辑的,但是我经常看到在各处几乎都使用“ int”的代码。在typedef荷兰国际集团往往不会导致代码看起来有点像这虽然:

DoSomething(EscalationLevel escalationLevel) {
    ...
}

那让我想知道哪个标记实际上在描述参数:参数类型或参数名称?


2
恕我直言,这似乎是毫无意义的练习,但我敢肯定有些人会不同意……
Nim

1
这些类型看起来像变量名。
长颈鹿队长

11
请注意,这给人的印象是它是类型安全的,但根本不是-typedef仅创建别名,但是没有什么阻止您将例如a传递给Minute具有声明为type的参数的函数Second
Jesper

2
@Mark:换一种方式来看。如果您在确定整数类型时犯了一个错误,或者将来出现了新的要求,因此您想更改它,您想更改一个typedef还是要搜索用于操纵一年的每个函数的代码,并且更改其签名?640k对任何人来说都足够了。typedef的相应缺点是,人们偶然或故意编写代码时,都依赖Year恰好是16位这一事实,然后它会更改并且代码会中断。
史蒂夫·杰索普

1
@Steve Jessop:我无法确定您是否认为这是一个好主意:-)第一部分似乎是赞成的,而后者则反对。我猜那有利弊。

Answers:


13

参数名称应说明其含义-在您的情况下为升级级别。类型是值的表示方式-在您的示例中添加typedefs会混淆函数签名的这一部分,因此我不建议这样做。

Typedef对于模板或要更改某些参数所用的类型(例如,从32位平台迁移到64位平台)非常有用。


那时这似乎是普遍共识。那么,您通常会坚持使用“ int”吗?在传输数据时,我必须在此应用程序中非常高效,是否只是在序列化期间转换为int16_t(或特定元素所需的最大表示类型)的情况?

@Mark:是的,这就是您应该这样做的方式。使用typedef表示使用的数据类型的大小,但不要区分在不同上下文中使用的同一类型。
比约恩博动

谢谢-只是为了澄清一下,您通常不会在代码中使用int8_t而不是int。.我想我主要担心的是“身份”之类的东西,它实际上是由数据库生成的身份。目前它是32位的,但我不确定这是否最终会变成64位。另外,int32_t vs int呢?int 通常与int32_t相同,但是我猜可能并不总是在其他平台上?我想我应该一般只使用“ int”,并在必要时使用“ int64_t” ..谢谢:-)

@Mark:像typedef一样重要的int32_t是,在不同平台上编译时,必须确保它们正确。如果您希望Identity在某个时候更改范围,我想我希望直接在所有受影响的代码中进行更改。但是我不确定,因为我需要更多地了解您的特定设计。您可能需要将其作为一个单独的问题。
比约恩博动

17

起初我以为“为什么不这样做”,但是后来我想到,如果您要花这么长的距离来分离这样的类型,那么请更好地利用该语言。代替使用别名,实际上定义类型:

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

之间没有性能差异:

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

和:

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

并且还具有增加参数验证和类型安全性的优点。例如,考虑使用原始类型处理金钱的代码:

float amount = 10.00;
CallSomeFunction(amount);

除了四舍五入的问题,它还允许任何可以转换为float的类型:

int amount = 10;
CallSomeFunction(amount);

在这种情况下,这没什么大不了的,但是隐式转换可能是难以确定的错误来源。typedef在这里使用a 并没有帮助,因为它们只是类型别名。

完全使用新类型意味着除非您对强制转换运算符进行编码,否则就没有隐式转换,这是一个坏主意,特别是因为它允许隐式转换。您还可以封装其他数据:

class Money {
  Decimal amount;
  Currency currency;
};

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

除非我们编写代码实现该功能,否则该功能将不适合该功能。意外转换是不可能的。我们还可以根据需要编写更复杂的类型,而无需太多麻烦。


1
您甚至可以编写一些可怕的宏来为您完成所有此类创建。(快来,Skizz。您知道您想要的。)

1
对于其中的某些类型,类型安全的单位库可能会有所帮助(tuoml.sourceforge.net/html/scalar/scalar.html),而不是为每个单元编写自定义类。
史蒂夫·杰索普

@Chris-绝对不是宏,但可能是模板类。正如Steve所指出的那样,这些类已经编写好了。
凯文·克莱恩

4
@Chris:BOOST_STRONG_TYPEDEF实际上是调用了宏;)
Matthieu M.

3

对原始类型使用typedef看起来更像C样式代码。

在C ++中,当您尝试重载诸如EventLevel和的函数时,会出现有趣的错误Hour。这使得多余的类型名称变得毫无用处。


2

我们(在我们公司)用C ++做很多事情。它有助于理解和维护代码。在团队之间移动人员或进行重构时,这很好。例:

typedef float Price;
typedef int64_t JavaTimestmap;

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

我们认为,从表示形式类型为维度名称创建typedef是一个好习惯。这个新名称代表了软件中的一般角色。参数的名称是本地角色。就像在User sender, User receiver。在某些地方,它可能是多余的,例如void register(User user),但我认为这不是问题。

后来,float由于预订的特殊舍入规则,可能会觉得不是最适合表示价格的想法,因此可以下载或实现一种BCDFloat(二进制编码的十进制)类型并更改typedef。没有搜索和替换,从工作floatBCDFloat这会的事实,有在你的代码可能有更多的花车硬化。

它不是灵丹妙药,它有自己的警告,但我们认为使用它总比没有好。


就像Mathieu M.在Skizz职位上所建议的那样BOOST_STRONG_TYPEDEF(float, Price),可以这样,但在一般项目上我不会走那么远。也许我会。我要睡了 :-)
Notinlist,2015年

1

typedef基本上可以让您为别名type
它为您提供了灵活性,避免了type names一次又一次地键入long ,并使您type更易于阅读,其中别名表示的意图或目的type

如果您希望typedef在项目中使用更易读的名称,则完全是一个选择问题。
通常,我避免typedef在原始类型上使用,除非它们很长才能被输入。我使参数名称更具指示性。


0

我永远不会做这样的事情。确保它们都具有相同的大小是一回事-但是您只需要将它们称为整数类型即可。


0

像这样使用typedef是可以的,只要最终使用它们的人不需要了解它们的基本表示形式。例如,如果要将PacketLength对象传递给printfscanf,则需要知道其实际类型,以便选择正确的转换说明符。在这种情况下,typedef只会增加某种程度的混淆,而无需购买任何回报。您最好将对象定义为int32_t

如果您需要强制执行每种类型的特定语义(例如允许的范围或值),那么最好创建一个抽象数据类型和对该类型进行操作的函数,而不仅仅是创建typedef。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.