C++ 相互 header 包含和前向声明
C++ Mutual header inclusion and forward declarations
我如何允许两个 class 相互包含,以便它们可以从一个转换为另一个。
Car.hpp
#ifndef CAR_HPP
#define CAR_HPP
#include "Truck.hpp"
class Car
{
public:
Car(int weight) : weight(weight) {}
Car(Truck data) : weight(ConvertFromTruck(data)) {}
private:
int weight;
int ConvertFromTruck(Truck data)
{
... //in real life there would be a lot more to transfer than just weight.
}
}
#endif //CAR_HPP
Truck.hpp
#ifndef TRUCK_HPP
#define TRUCK_HPP
#include "Car.hpp" //Obviously won't be included because of the CAR_HPP include guard
class Truck
{
public:
Truck(int weight) : weight(weight) {}
Truck(Car data) : weight(ConvertFromCar(data)) {}
private:
int weight;
int ConvertFromCar(Car data)
{
...//in real life there would be a lot more than just weight
}
}
#endif //TRUCK_HPP
Main.cpp
#include "Car.hpp"
#include "Truck.hpp"
int main()
{
Car newCar(42);
Truck newTruck(newCar);
return 0;
}
所以显然 Truck.hpp 不能真正包含 Car.hpp 因为 CAR_HPP 已经定义了。另外,Truck.hpp 不能前向声明 class Car;
因为 Truck(Car data)...
需要一个完整的类型,而前向声明的 class 不是一个完整的类型。
看起来像这样:Forward declaration being ignored?但是没有答案。
本主题声明不相互包括headers。 Forward Declarations and Includes
我会尽量避免这种情况,但我怎样才能获得可以接收卡车并正确转换的汽车和可以接收汽车并正确转换的卡车?
有什么方法可以使用:
operator Car() { ... }
和 operator Truck() { ... }
以便可以将汽车铸造成卡车,反之亦然?
在声明中
int ConvertFromTruck(Truck data)
Truck
需要是 complete 类型,这意味着编译器必须可以使用 Truck
的 class 定义。这就是你的问题。
幸运的是有一个解决方案:通过const
引用传递Truck
:
int ConvertFromTruck(const Truck& data)
这里编译器只需要 incomplete 类型用于 Truck
,而 forward class 声明 比 #include
就足够了。这在 run-time 上也非常优越,因为您在函数运行时没有获取 Truck
的值副本(尽管编译器可能会优化该副本)。
对构造函数(即 Car(const Truck& data)
)和 Truck
class 执行相同的操作。
请注意,我使用 const
参考而不是非 const
参考有两个原因 (i) 你 不想 能够修改传递的对象,并且 (ii) 匿名临时 可以绑定到 const
引用。
我如何允许两个 class 相互包含,以便它们可以从一个转换为另一个。
Car.hpp
#ifndef CAR_HPP
#define CAR_HPP
#include "Truck.hpp"
class Car
{
public:
Car(int weight) : weight(weight) {}
Car(Truck data) : weight(ConvertFromTruck(data)) {}
private:
int weight;
int ConvertFromTruck(Truck data)
{
... //in real life there would be a lot more to transfer than just weight.
}
}
#endif //CAR_HPP
Truck.hpp
#ifndef TRUCK_HPP
#define TRUCK_HPP
#include "Car.hpp" //Obviously won't be included because of the CAR_HPP include guard
class Truck
{
public:
Truck(int weight) : weight(weight) {}
Truck(Car data) : weight(ConvertFromCar(data)) {}
private:
int weight;
int ConvertFromCar(Car data)
{
...//in real life there would be a lot more than just weight
}
}
#endif //TRUCK_HPP
Main.cpp
#include "Car.hpp"
#include "Truck.hpp"
int main()
{
Car newCar(42);
Truck newTruck(newCar);
return 0;
}
所以显然 Truck.hpp 不能真正包含 Car.hpp 因为 CAR_HPP 已经定义了。另外,Truck.hpp 不能前向声明 class Car;
因为 Truck(Car data)...
需要一个完整的类型,而前向声明的 class 不是一个完整的类型。
看起来像这样:Forward declaration being ignored?但是没有答案。
本主题声明不相互包括headers。 Forward Declarations and Includes
我会尽量避免这种情况,但我怎样才能获得可以接收卡车并正确转换的汽车和可以接收汽车并正确转换的卡车?
有什么方法可以使用:
operator Car() { ... }
和 operator Truck() { ... }
以便可以将汽车铸造成卡车,反之亦然?
在声明中
int ConvertFromTruck(Truck data)
Truck
需要是 complete 类型,这意味着编译器必须可以使用 Truck
的 class 定义。这就是你的问题。
幸运的是有一个解决方案:通过const
引用传递Truck
:
int ConvertFromTruck(const Truck& data)
这里编译器只需要 incomplete 类型用于 Truck
,而 forward class 声明 比 #include
就足够了。这在 run-time 上也非常优越,因为您在函数运行时没有获取 Truck
的值副本(尽管编译器可能会优化该副本)。
对构造函数(即 Car(const Truck& data)
)和 Truck
class 执行相同的操作。
请注意,我使用 const
参考而不是非 const
参考有两个原因 (i) 你 不想 能够修改传递的对象,并且 (ii) 匿名临时 可以绑定到 const
引用。