C++:重载数学运算符
我希望重载加法运算符,并让它添加同一类的两个对象。当我在头文件的类声明中声明这个“operator+”原型函数时,我将两个对象作为参数传递。我收到编译器错误,指出“二进制‘运算符 +’有太多参数”。我在网上寻找答案,发现在编译出来的头文件中的类声明之外声明了一个内联函数。我想知道我做错了什么或者我是否在这里遗漏了一些东西。这是我在头文件中使用的代码。
class Person
{
private:
int age;
double weight;
public:
Person::Person(); //default constructor
Person::~Person(); //default desctructor
Person operator+(Person r, Person i);
};
编译时会出现我上面提到的错误。下面是编译良好的代码。
class Person
{
private:
int age;
double weight;
public:
Person::Person(); //default constructor
Person::~Person(); //default desctructor
};
inline Person operator+(Person r, Person i)
{
return Person(0,0);
}
I am looking to overload, let's say, the addition operator and have it add two objects of the same class. When I declare this "operator+" prototype function in the class declaration in the header file, I pass in both objects as parameters. I get a compiler error saying that "binary 'operator +' has too many parameters". I was searching around for an answer online and found out that declaring an inline function just outside the class declaration in the header file compiled out. I'm wondering what I was doing wrong or if I'm missing something here. Here is the code I am using in the header file.
class Person
{
private:
int age;
double weight;
public:
Person::Person(); //default constructor
Person::~Person(); //default desctructor
Person operator+(Person r, Person i);
};
This compiles with the error I mentioned above. Below is the code that compiles fine.
class Person
{
private:
int age;
double weight;
public:
Person::Person(); //default constructor
Person::~Person(); //default desctructor
};
inline Person operator+(Person r, Person i)
{
return Person(0,0);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
如果您将 oparator+ 声明为实例函数,则第一个参数将作为 this 对象传递,因此您只需要一个参数。阅读本文以获取更多信息,特别是尝试理解
const
概念:http://www.cs.caltech.edu/courses/cs11/material/cpp/donnie/cpp-ops.html
中建议的最佳方法引用的文章是:
如果您决定使用
const
版本,请记住您将只能在this
和i 上调用
const
方法参考文献。这是首选方式。我引用的文章详细解释了首先重载
+=
然后使用+=
定义+
的想法。这是一个好主意,因为+=
运算符必须单独重载。另外 - David Rodríguez 建议将
operator+
实现为自由函数,而不管 += 是否存在。If you declare
oparator+
as an instance function then the first argument is being passed asthis
object and thus you need only one more argument. Read this for more info, in particular try to understand theconst
concept:http://www.cs.caltech.edu/courses/cs11/material/cpp/donnie/cpp-ops.html
The best approach as advised in the referenced artice is:
if you decide to use
const
version remember that you will only be able to callconst
methods onthis
andi
references. This is the preferred way.The article I referenced to explains the idea of overloading
+=
first and then defining+
using+=
in more details. This is a good idea since+=
operator must be separately overloaded.Additionally - David Rodríguez suggests
operator+
to be implemented as a free function regardless of the presence of += .每个成员函数都有一个隐式的第一个参数:
this
。对于运营商来说也是如此。因此,如果你想让operator+()
成为一个成员,它必须只接受一个参数,即右操作数,因为左操作数已经是this
了。但是,对于可以是成员函数或自由函数的二元运算符,我的经验法则是使它们成为对称处理其参数的自由函数(
operator+()
不会改变以下任何一个)其操作数),并将它们设为不更改的成员函数(operator+=()
更改其左操作数,但不更改其右操作数)。此外,对于所有算术运算符,有一个很好的模式可以根据它们的组合赋值版本来实现它们。也就是说,
operator+()
将基于operator+=()
,-
基于-=
等。除此之外,您不想不必要地复制类对象,但通常希望它们按
const
引用传递。基于此,我的
operator+
规范版本将是:但是。关于运算符重载的最重要的经验法则可能是:< strong>不要这样做。这可能听起来很矛盾,但大多数情况下命名函数比运算符要好得多,因为后者使代码的可读性低于普通函数。在编写代码时,可读性应该是最重要的方面。 除非运算符在应用程序域中具有明确且无可争议的含义,否则不要为类重载它。
在您的示例中,运算符
+
应用于两个人肯定没有没有明确且无可争议的含义。在现实世界中添加到人意味着什么? (我能想到的第一个含义不会是一个人,而是一群人。:)
)因此,除非为您的 Person 类重载此运算符是一项家庭作业,否则我强烈建议您不要这样做。 (如果这是一项作业,我会责怪老师找到这么糟糕的例子。)
Every member function has an implicit first argument:
this
. This is also true for operators. Therefor, if you want to makeoperator+()
a member, it must only take one argument, the right operand, because the left operand already isthis
.However, for binary operators that can be either a member function or a free function, my rule of thumb is to make those a free function which treat their arguments symmetrically (
operator+()
doesn't change either of its operands), and make those a member function which don't (operator+=()
changes its left operand, but not its right).Further, for all arithmetical operators, there's a nice pattern to implement them based on their combined assignment versions. That is,
operator+()
would be based onoperator+=()
,-
based on-=
etc.Add to this that you don't want to needlessly copy class objects, but usually want them to be passed per
const
reference.Based on this, my canonical versions of
operator+
would be:However. What's probably the most important rule of thumb regarding operator overloading is this: Don't do it. This might sound paradoxical, but most often named functions are a lot better than operators, because the latter make the code less readable than normal functions would. And when writing code, readability should be the most important aspect. Unless an operators has a clear and undisputed meaning in the application domain, don't overload it for a class.
In your example there certainly is no clean and undisputed meaning of operator
+
applied to two persons. What does it mean in the real world to add to persons? (The first meaning I could think of wouldn't have a single person as a result, but an array of persons.:)
)So, unless overloading this operator for your
Person
class is a homework assignment, I would strongly advice against it. (And if it is an assignment, I'd blame the teacher for finding such a bad example.)这是一个在类中工作 += 的示例。
Here is an example for a working += in a class.
根据我的阅读,最佳实践是将operator+声明为友元函数而不是成员函数。
cplusplus.com 对这个问题进行了全面的讨论:
二元运算符是朋友 - 为什么?< /a>
Meyers 在他的书《Effective C++ IIRC》中也对此进行了讨论。
引用geustgulkan的评论:
所以你可能想要的是:
From what I've read the best practice is to declare
operator+
as a friend function and not as a member function.There's a whole discussion of this issue over at cplusplus.com:
Binary operators as friends - why?
Meyers also discusses it in his book Effective C++ IIRC.
Quoting from the comment of geustgulkan:
So what you probably want is:
我只有一个建议:使用 Boost.Operators。
据我所知,有两个优点:
addable
几乎是不言自明的Boost.Operators 提供了一个参考表,其中为每个行为列出了应定义的所需运算符以及将自动生成的运算符。
保持界面紧凑并将一些文档直接注入代码中非常方便。
I only have one advise: use Boost.Operators.
There are 2 advantages as far as I can see:
addable
is pretty much self-explanatoryBoost.Operators provides a reference table, which for each behavior lists the required operators that should be defined and those that will be generated automatically.
It's very handy to keep the interface compact and to inject some documentation right into the code.
似乎您进行了成员运算符+声明,无意引用任何人员实例数据:成员运算符与任何成员方法一样,接受调用它的实例作为参数。
如果由于某种原因您需要使其成为成员(例如,访问私有状态),您可以将其声明为静态。
Seems you made the member operator+ declaration with no intent to reference any Person-instance data: the member operator, as any member method, accepts the instance on which it is invoked as an argument.
If for some reason you need to make it a member (e.g., access to private state), you can declare it static.
我同意agsamek和履行机构的论点。我添加了一些额外的注意事项,
没有任何带有 2 的构造函数
参数,这是一个错误(但是
编译器尚未发出信号)
有 2 个参数的运算符你不能
使用实例成员,但您必须
使用一个函数。我避免声明
朋友功能因为你打破
该类的封装(它将
更难维护)。它是
更好地实现一些“访问器
方法”来获取对象的内部
价值观;
中的声明和定义
相同的地方(通常在 .h 文件中),所以更少
可操作的。此外,扩展
该代码的一部分位于编译器处
酌情权。
接下来按照我的解决方案来解决你的问题:
I agree with argumentations of agsamek and sbi. I add some extra considerations
doesn't have any costructor with 2
arguments and that's an error (but
not yet signaled by compiler)
operator with 2 arguments you can't
use an instance member but you must
use a function. I avoid to declare
friend functions because you break
encapsulation of that class (it will
be more difficult to maintain). It's
better to implement some "accessor
methods" to get object's internal
values;
declaration and definition in the
same place (normally in .h file) so in less
manutenable. Moreover the expansion
of that code is at compiler
discrection.
Next follow my solution to your question:
实现:
当您重载二元运算符(在本例中为+)作为成员函数时,调用该运算符的对象将隐式传递给该函数,并且您只需要显式传递一个参数
因此您的主函数应该是这样的
Implementation :
When you overload a binary operator(+ in this case) as member function, the object on which the operator is invoked is passed implicitly to the function and you need to pass only one argument explicitly
Thus your main function should be like this