将参数传递给函数

时间:2011-02-15 16:27:20

标签: c++ coding-style

将arg传递给一个类型不是“完全匹配”的函数是否是一个糟糕的编程原则,但是对这种类型进行了简单或用户定义的转换?例如:

void f(bool option);

以及后来的主要内容(这是非常假设的,所以请不要就该代码提供建议):

int a = getSomeValue();

f(a);//here instead of bool I'm passing int - is it a bad programming practice or not?

6 个答案:

答案 0 :(得分:6)

我认为大多数人都会考虑这种不良做法。写作f(a !=0)更加清晰,并且简明扼要地表达了意图。

答案 1 :(得分:6)

转换为bool是一种特殊情况,因为它的行为不像整数转换,所以很多人都喜欢看到它,并使用!= 0而不是强制转换。

如果您将int传递给了long的函数,那么我当然不希望看到任何类型的显式转换混乱。同样,我也不希望char*投放到const char*以便将其传递给strlen。那些转换“实际上并没有做任何事情”:它们总是保留输入的值,而在指针的情况下,它不会让你对使用原始指针无法做的referand做任何事情。 / p>

如果你将一个unsigned long传递给一个带unsigned int的函数,那么在某些实现上(但绝不是所有常见的函数),这是一个“缩小转换”,取决于值可以通过取模数来丢弃信息。在这种情况下,将转换显式化通常是一个好主意,这样随意读者就不必检查函数签名就能意识到它发生了。这些转换“做点什么”可能会令人惊讶。

在整数和浮点类型之间进行转换时也是如此:尽管int -> double对于您将看到的几乎任何实现都是无害的,double -> int对某些值有未定义的行为,所以你不要希望读者想念它。

然而,有时会提供非常复杂的用户定义转换,以便您可以调用函数并从隐式转换中受益。因此,对于那些,您应该遵循在转换中定义的任何API中的使用示例。

例如,如果Foo有一个隐式构造函数需要std::string,而某些函数bar需要Foo,那么它与POV的POV并不完全相同调用者bar比API仅提供显式转换,但两次重载bar,一次采用Foo,另一次采用std::string,但将其直接转换为Foo {1}}并呼叫另一个。因此,在这样的情况下依赖转换并不比重载函数更糟糕。后者不被视为本世纪的罪行。除了Python程序员。

答案 2 :(得分:2)

是的,我认为这是糟糕的编程习惯。

依赖隐式转换可能会导致非常奇怪的错误。 我曾经遇到过以下问题。 这一切都始于这样的功能:

void doSomething (ClassX x, ClassY y, bool b);

使用以下代码调用此函数:

ClassX x;
ClassY y;
doSomething (x, y, true);

后来有人认为doSomething的论点必须改变,因为doSomething现在也需要ClassZ的一个实例。此外,布尔参数在许多情况下都是正确的,因此它被更改为默认参数,如下所示:

void doSomething (ClassX x, ClassY y, ClassZ z, bool b=true);

虽然大部分代码已更改,但之前显示的调用未更改。 奇怪的是,ClassZ有一个非显式构造函数,以bool作为参数:

class ClassZ
   {
   public:
      ClassZ(bool b);
   };

以下是发生了什么事。这个电话:

ClassX x;
ClassY y;
doSomething (x, y, true);

编译器默默地将其转换为此内容:

ClassX x;
ClassY y;
doSomething (x, y, ClassZ(true), true);

第四个参数是默认值。

多年以后,我们发现某些内容无法正常工作,经过大量调试后,我们发现此调用是导致问题的原因。

因此:

  • 从不依赖隐式转换
  • 将带有1个参数的构造函数标记为显式
  • 尽量避免使用默认参数

答案 3 :(得分:1)

如果您将short变量传递给f(int),那就没关系了。但相反的是危险的(即intshort - 可能溢出!),大多数编译器都不会高兴,所以会给你警告。

至于f(bool),是的,当你在调用f(a!=0)时写f时,意图会更清晰。我们这里是为了便于阅读,而不是简单地将a作为f(a)传递是危险的。

答案 4 :(得分:1)

这完全取决于背景。

在这个非常具体的情况下,您将在您的问题中找到。我更喜欢显式测试而不是0的隐式转换为false(但这也是因为变量和函数的名称如果用不同的名字命名,那么我可能不介意)。

但还有其他情况,隐式转换很好:

std::ifstream f("File");
if (f) 
{
    // Testing f is relatively standard.
}

任何时候都有信息丢失。我希望有一个明确的演员报告,解释为什么信息丢失是好的。

long theDistanceToLodond = getDistance("ToLondon");
InsideM25Action(static_cast<short>(theDistanceToLondon)); // All distances inside the M25 fit in a short therefore no information loss.

但是没有信息丢失的强制转换不应该有一个显式的强制转换(它会过多地聚集代码而不提供任何好处)。我不会指望显式向下转换指向基类等等。

答案 5 :(得分:0)

由于您使用的是C ++,您应该已经完成​​了:

   int a = getSomeValue();
   f(static_cast<bool>(a));

这肯定会表达你的意图,这就是为什么我们有很多类型的显式演员。