【问题标题】:How can I make numbers passed to a function type-safe?如何使数字传递给函数类型安全?
【发布时间】:2020-03-27 12:01:50
【问题描述】:

我的函数应该采用 ID 号(一个 int),但我注意到我不小心传递了不同事物的 ID 号,这破坏了我的程序。因此,我尝试执行以下操作以使其类型安全:

struct Number
{
    int ID;
    int operator =(const int& rhs) { ID = rhs; }
}

struct DogID : Number { }
struct CatID : Number { }

void functionTakingDogID(DogID ID) { }
void functionTakingCatID(CatID ID) { }

int main()
{
     DogID dogID;
     dogID = 5; // But the = operator overload isn't inherited
}

我创建类来保存数字的唯一原因是为了防止传递错误的 ID 号。我使用从 Number 继承的原因是,像 Dog 和 Cat 这样的任何类都可以被视为 ID 号(分配给)。

能够将 ID 号发送到函数但确保向其发送正确 ID 的最简洁的方法是什么?我不确定枚举类是否是一个选项,因为 ID 是在运行时给出的。

我还发现:

除赋值 (operator=) 之外的所有重载运算符都由派生类继承。

运算符 = 是唯一未继承的运算符重载的原因是考虑到派生类可能有额外的成员,它被认为风险太大吗?

【问题讨论】:

  • BOOST_STRONG_TYPEDEF 适用于原语。我只是在阅读它,会在一秒钟内找到一个骗子
  • 你需要operator=吗?也许您可以在每个派生类的构造函数中传递 ID 并在那里进行验证。
  • @Yksisarvinen 严格来说,不需要 operator = 重载,我可以改为使用 dogID.ID = 5 而不是 dogID = 5。我只是重载了它,因此我可以将 dogID 视为一个数字在使它成为类型安全之前我会这样做。

标签: c++ type-safety


【解决方案1】:

您可以做的是为您的号码使用标签

template<typename Tag>
struct Number
{
    int ID;
    Number &operator =(int rhs) { ID = rhs; return *this;}
};

using DogID = Number<struct DogIdTag>;
using CatID = Number<struct CatIdTag>;

int main()
{
     DogID dogID;
     dogID = 5; // But the = operator overload isn't inherited
}

这个想法是给你的Number 类一个标签。这样做将确保Number&lt;Tag1&gt;Number&lt;Tag2&gt; 的类型不同

但是,在一般架构中,我不建议在 int 上使用 operator=,因为您会失去一点类型安全性。

例如,在这段代码中:

void f(int accountId) {DogId id = accountId;}

这不是很好,我建议你只使用这样的东西:

DogId id = DogId{anInteger}

并继续使用我们在上面看到的模板Number

注意

  1. operator= 函数必须返回对当前对象的引用,而不是 int。
  2. 从需要返回某些内容的函数中不返回某些内容是很危险的。在 C 中这是危险的,在 C++ 中这是未定义的行为。

【讨论】:

  • 谢谢,这个解决方案看起来不错。并且不需要使用 boost 之类的外部库。
猜你喜欢
  • 2020-04-10
  • 2018-02-14
  • 2019-08-07
  • 2019-09-09
  • 2018-08-12
  • 2016-02-28
  • 1970-01-01
  • 1970-01-01
  • 2017-07-19
相关资源
最近更新 更多