C++ C++;:在两个不同的类中重载同一运算符时出现问题
首先非常感谢你提供的线索 我在完成作业时遇到了一个特殊的问题。我很确定名称空间、包括、头文件和所有这些东西都有问题,但我真的不知道出了什么问题 重点是:我需要两个不同的类(比如C++ C++;:在两个不同的类中重载同一运算符时出现问题,c++,namespaces,include,operator-overloading,C++,Namespaces,Include,Operator Overloading,首先非常感谢你提供的线索 我在完成作业时遇到了一个特殊的问题。我很确定名称空间、包括、头文件和所有这些东西都有问题,但我真的不知道出了什么问题 重点是:我需要两个不同的类(比如Car和CarShop),每个类都必须使操作员过载+ Car->Car&operator+(const Car&c)(应“添加”两辆车) CarShop->CarShop&operator+(const Car&c)(应将汽车“添加”到现有的CarShop) 在文件CarShop.h中,我需要#包括“car.h”,因为
Car
和CarShop
),每个类都必须使操作员过载+
->Car
(应“添加”两辆车)Car&operator+(const Car&c)
->CarShop
(应将汽车“添加”到现有的CarShop)CarShop&operator+(const Car&c)
CarShop.h
中,我需要#包括“car.h”
,因为它与不同的“car”对象一起工作。此外,在我的主要测试类中,比如说main.cpp
,我还需要#包括“car.h”
和#包括“carshop.h”
我在这里得到了错误消息。VisualStudio(我们将它作为IDE使用)给了我“LNK1169和LNK2005”错误,解释说“一个或多个符号是同时定义的”
有人能帮我吗?为了避免这两个重载运算符之间的冲突,我应该怎么做
这两个操作符(2个重载操作符)都被声明为各自类的友元函数(在.h文件中),并在各自的.cpp文件中实现。您正在成倍地声明一个汽车类型。在您的
main.cpp
中包括car.h
和carshop.h
,而carshop.h
已经包括car.h
。如果没有包含保护,则会导致链接器错误
你有两种可能:
- 从
main.cpp中删除
#包括“Car.h”
- 使用包括这样的防护装置:
anyfile.h
:
#pragma once
/* ... the rest of your code ... */
#ifndef MYHEADER_H
#define MYHEADER_H
/* ... your code here ... */
#endif
如果您的编译器不支持#pragma once
指令,您可以始终在标题中使用标准的宏保护,尽管有点麻烦:
myheader.h
:
#pragma once
/* ... the rest of your code ... */
#ifndef MYHEADER_H
#define MYHEADER_H
/* ... your code here ... */
#endif
您正在声明一种汽车类型。在您的
main.cpp
中包括car.h
和carshop.h
,而carshop.h
已经包括car.h
。如果没有包含保护,则会导致链接器错误
你有两种可能:
- 从
main.cpp中删除
#包括“Car.h”
- 使用包括这样的防护装置:
anyfile.h
:
#pragma once
/* ... the rest of your code ... */
#ifndef MYHEADER_H
#define MYHEADER_H
/* ... your code here ... */
#endif
如果您的编译器不支持#pragma once
指令,您可以始终在标题中使用标准的宏保护,尽管有点麻烦:
myheader.h
:
#pragma once
/* ... the rest of your code ... */
#ifndef MYHEADER_H
#define MYHEADER_H
/* ... your code here ... */
#endif
简短回答:不要将这些操作符声明为好友 长答覆: 当一个函数被声明为friend时,这意味着它不属于它被“声明”的类(实际上,您没有在那里声明该函数),您只是说该函数(请注意,它将是一个C函数,而不是成员函数)是该类的朋友,并且可以访问私有数据
您可能正在使用friend,因为您看到代码将其用于运算符简短回答:不要将这些运算符声明为friend 长答覆: 当一个函数被声明为friend时,这意味着它不属于它被“声明”的类(实际上,您没有在那里声明该函数),您只是说该函数(请注意,它将是一个C函数,而不是成员函数)是该类的朋友,并且可以访问私有数据
您可能正在使用friend,因为您看到的代码将其用于运算符,正如其他人所指出的,您不能仅将其声明为friend:
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,则有必要声明友元运算符。但是,由于这些是您的类,您最好将运算符声明为成员:
Car operator+(const Car &c2); // this is declared inside the Car class
CarShop operator+(const Car &c); // this is declared inside the CarShop class
这里不需要朋友,因为他们是会员。严格来说,如果您想访问汽车的私人会员,您可能希望将
CarShop::operator+(const Car&)
声明为汽车类中的朋友。但是对于Car::operator+(const Car&)
来说,这是绝对没有必要的。正如其他人所指出的,你不能仅仅把他们宣布为朋友:
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,则有必要声明友元运算符。但是,由于这些是您的类,您最好将运算符声明为成员:
Car operator+(const Car &c2); // this is declared inside the Car class
CarShop operator+(const Car &c); // this is declared inside the CarShop class
不需要