使用一个参数调用重载函数,但我认为我传递了两个参数
我最近重构了这样的代码(MyClass
到 MyClassR
)。
#include <iostream>
class SomeMember
{
public:
double m_value;
SomeMember() : m_value(0) {}
SomeMember(int a) : m_value(a) {}
SomeMember(int a, int b)
: m_value(static_cast<double>(a) / 3.14159 +
static_cast<double>(b) / 2.71828)
{}
};
class MyClass
{
public:
SomeMember m_first, m_second, m_third;
MyClass(const bool isUp, const int x, const int y)
{
if (isUp)
{
m_first = SomeMember(x);
m_second = SomeMember(y);
m_third = SomeMember(x, y);
}
else
{
m_first = SomeMember(y);
m_second = SomeMember(x);
m_third = SomeMember(y, x);
}
}
};
class MyClassR
{
public:
SomeMember m_first, m_second, m_third;
MyClassR(const bool isUp, const int x, const int y)
: m_first(isUp ? x : y)
, m_second(isUp ? y : x)
, m_third(isUp ? x, y : y, x)
{
}
};
int main()
{
MyClass a(true, 1, 2);
MyClassR b(true, 1, 2);
using namespace std;
cout.precision(10);
cout
<< "a:" << endl
<< "\tfirst: " << a.m_first.m_value
<< "\tsecond: " << a.m_second.m_value
<< "\tthird: " << a.m_third.m_value << endl;
cout
<< "b:" << endl
<< "\tfirst: " << b.m_first.m_value
<< "\tsecond: " << b.m_second.m_value
<< "\tthird: " << b.m_third.m_value << endl;
return 0;
}
- 错误是什么,
- 为什么会编译(使用 VC6 以及 VC9 警告级别 4 进行测试:没有投诉)以及
- 正确的方法是什么?
我(假设)我已经有了所有这些答案,但我认为这是一个值得分享的有趣问题。
更新
扩展代码,使其可以“复制、粘贴和执行”。 VC9 也没有给我任何抱怨,所以 VC6 不是这里的问题。
为了完整起见,输出为:
a:
first: 1 second: 2 third: 1.054069532
b:
first: 1 second: 2 third: 1.004499999
I recently refactored code like this (MyClass
to MyClassR
).
#include <iostream>
class SomeMember
{
public:
double m_value;
SomeMember() : m_value(0) {}
SomeMember(int a) : m_value(a) {}
SomeMember(int a, int b)
: m_value(static_cast<double>(a) / 3.14159 +
static_cast<double>(b) / 2.71828)
{}
};
class MyClass
{
public:
SomeMember m_first, m_second, m_third;
MyClass(const bool isUp, const int x, const int y)
{
if (isUp)
{
m_first = SomeMember(x);
m_second = SomeMember(y);
m_third = SomeMember(x, y);
}
else
{
m_first = SomeMember(y);
m_second = SomeMember(x);
m_third = SomeMember(y, x);
}
}
};
class MyClassR
{
public:
SomeMember m_first, m_second, m_third;
MyClassR(const bool isUp, const int x, const int y)
: m_first(isUp ? x : y)
, m_second(isUp ? y : x)
, m_third(isUp ? x, y : y, x)
{
}
};
int main()
{
MyClass a(true, 1, 2);
MyClassR b(true, 1, 2);
using namespace std;
cout.precision(10);
cout
<< "a:" << endl
<< "\tfirst: " << a.m_first.m_value
<< "\tsecond: " << a.m_second.m_value
<< "\tthird: " << a.m_third.m_value << endl;
cout
<< "b:" << endl
<< "\tfirst: " << b.m_first.m_value
<< "\tsecond: " << b.m_second.m_value
<< "\tthird: " << b.m_third.m_value << endl;
return 0;
}
- What is the error,
- why does it compile (tested with VC6 as well as VC9 warning level 4: no complaints) and
- what is the right way of doing it?
I (assume) I already have all these answers but I think it's and interesting problem to share.
Update
Extended code so it's "copy & paste & execute"-able. VC9 gave me no complaints either so VC6 is not the problem here.
For completeness, the output is:
a:
first: 1 second: 2 third: 1.054069532
b:
first: 1 second: 2 third: 1.004499999
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我不确定您到底期望什么,但让我们开始......
首先,放弃 VC6。 说真的。使用它是一个巨大的问题,因为它不符合标准并且排除了很多选项。正确使用它就像玩俄罗斯轮盘赌。
您的
m_third
构造函数并未执行您认为的操作。您不能编写这样的条件表达式:“几个参数”在 C++ 中不是有效的表达式,并且条件运算符适用于表达式。代码可以编译,因为它仍然正确,只是没有执行您想要的操作。它不使用“多个参数”,而是计算序列点运算符 (
,
),该运算符仅采用表达式的 last 值,因此您的条件实际上等效于:<代码> isUp ? y : x正确的方法是使用两个条件:
m_third(isUp ? x : y, isUp ? y : x)
SomeMember<的第三个构造函数< /code> 是错误的,该值可能溢出,产生负值 - 我非常怀疑这就是你想要的。
I’m not sure what exactly you expect but let’s start …
First off, ditch VC6. Seriously. Using it is a huge problem since it’s just not standards conforming and precludes a lot of options. Using it correctly is like playing Russian roulette.
Your constructor of
m_third
doesn’t do what you think it does. You cannot write a conditional expression like this: “several parameters” is not a valid expression in C++, and the conditional operator works on expressions.The code compiles because it’s still correct, it just doesn’t do what you want it to. Instead of using “several parameters”, it evaluates the sequence point operator (
,
) which just takes the last value of the expression, so your conditional is effectively equivalent to:isUp ? y : x
The right way is to use two conditionals:
m_third(isUp ? x : y, isUp ? y : x)
The third constructor of
SomeMember
is wrong, the value may overflow, yielding a negative value – I highly doubt that that’s what you want.这看起来是错误的。第一个
x
是一个毫无意义的表达式,因为它没有副作用,并且不使用结果,那么:
的两侧具有相同的值和副作用,因此 < code>?: 可以被消除,因为?
之前的表达式也没有副作用。但现在它不执行原始代码的操作...这是错误吗?
This looks wrong to be. The first
x
is a pointless expression as it has no side effects and the result is not used, then the two sides of the:
have the same value and side effects so?:
can be elimintated as the expression before the?
also has no side effects.But now it doesn't do what the original code does... is this the error?
我猜你的意图是展示逗号运算符与三元 ? 组合的某种天真的用法,也许隐藏着一些聪明且意想不到的运算符优先级陷阱,但我认为代码绝对是人为的。如果这是重点,那么我会说“正确的做法”是不要使用 C++ 或在使用它之前先学习它。是的,它有许多看起来像“怪癖”的构造,您可以创建许多编译器接受的看起来奇怪的代码。通过使用 C++,我想说您应该了解这些工具。
因为它不包含错误,并且它是正确的 C++ 代码,没有歧义。
I guess your intention is to show some kind of naive usage of comma operator in combination with ternary ?, perhaps there is some clever and unexpected operator priority gotcha hidden, but that I think the code is absolutely artificial. If this is the point, than I would say the "right way of doing it" is do not use C++ or first learn it before using it. Yes, it has many constructs which may look like "quirks" and you can create a lot of strangely looking code accepted by a compiler. By using C++ I would say you are assumed to know the tools.
Because it contains no error and it is a correct C++ code with no ambiguities.