将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?
答案 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);
第四个参数是默认值。
多年以后,我们发现某些内容无法正常工作,经过大量调试后,我们发现此调用是导致问题的原因。
因此:
答案 3 :(得分:1)
如果您将short
变量传递给f(int)
,那就没关系了。但相反的是危险的(即int
到short
- 可能溢出!),大多数编译器都不会高兴,所以会给你警告。
至于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));
这肯定会表达你的意图,这就是为什么我们有很多类型的显式演员。