首先非常感谢你的线索。
我在尝试完成作业时遇到了一个特殊问题。我很确定命名空间,包含,头文件和所有这些东西都有问题,但是我真的不知道出了什么问题。
关键在于:我需要两个不同的类(比如Car
和CarShop
),每个类都必须重载运算符+。
Car
- > Car &operator+(const Car &c)
(应该“添加”两辆车)CarShop
- > CarShop &operator+(const Car &c)
(应该“添加”汽车到现有的CarShop)在文件CarShop.h
中,我需要#include "car.h"
,因为它对不同的“汽车”对象有很多作用。此外,在我的主要测试课程中,我要说main.cpp
,我还需要#include "car.h"
和#include "carshop.h"
。
我收到错误消息。 Visual Studio(我们正在使用它作为我们的IDE)给出了“LNK1169& LNK2005”错误,解释了“同时定义了一个或多个符号”。
有人可以帮我吗?我应该怎么做才能避免两个重载运算符之间的冲突?
PS。它们(2个重载运算符)都被声明为各自类的友元函数(在.h文件中),并在各自的.cpp文件中实现。
答案 0 :(得分:2)
正如其他人所指出的那样,你不能只将这些声明为朋友:
Car &operator+(const Car &c);
CarShop &operator+(const Car &c);
即使你可以编译和链接它,它也行不通。并且您无法链接,因为它们具有相同的签名(签名中不包含返回类型)。您有两种选择:要么有非成员朋友,要么有成员函数(不需要朋友声明)。如果你想要非成员朋友,你应该像这样声明它们,指定两个操作数:
Car operator+(const Car &c1, const Car &c2);
CarShop operator+(const CarShop &cs, const Car &c);
请注意,正如James指出的那样,这些运算符不应该返回引用。它们按定义返回新实例。
但是,只有当第一个参数的类型与您控制的任何类不同时,才需要使用朋友操作符。例如,如果第一个参数的类型为std :: string或int,则需要声明friend运算符。但是,由于这些是您的类,因此最好将运算符声明为成员:
Car operator+(const Car &c2); // this is declared inside the Car class
CarShop operator+(const Car &c); // this is declared inside the CarShop class
这里不需要朋友,因为他们是会员。严格地说,如果您想访问Car的私人会员,您可能希望将CarShop::operator+(const Car&)
声明为Car类中的朋友。但对于Car::operator+(const Car&)
来说,这绝对没必要。
答案 1 :(得分:1)
您正在多次声明Car类型。在main.cpp
car.h
中,carshop.h
和carshop.h
包括car.h
,#include "Car.h"
已包含main.cpp
。如果没有包含保护,则会导致链接器错误。
您有两种可能性:
anyfile.h
#pragma once
/* ... the rest of your code ... */
#pragma once
:
myheader.h
在你的编译器不支持#ifndef MYHEADER_H
#define MYHEADER_H
/* ... your code here ... */
#endif
指令的情况下你总是可以使用标准,虽然你的标题中有一些麻烦的宏观守卫:
{{1}}:
{{1}}
答案 2 :(得分:1)
简短回答:不要将这些运营商声明为朋友。
答案很长:
当一个函数被声明为friend时,它意味着它不属于它被“声明”的类(事实上,你没有在那里声明函数),你只是说该函数(注意它将是 您可能正在使用朋友,因为您看到了使用该代码的运算符<< (使用std :: ostream),但这不能成为因为你需要成为std :: ostream的成员函数。删除朋友,你将使“这个”成为第一个操作员。