C++ 相互头文件包含和前向声明

Que*_*ble 2 c++ header-files forward-declaration

我如何允许两个类相互包含,以便它们可以从一个类转换为另一个类。

汽车.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
Run Code Online (Sandbox Code Playgroud)

卡车.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
Run Code Online (Sandbox Code Playgroud)

主程序

#include "Car.hpp"
#include "Truck.hpp"

int main()
{
    Car newCar(42);
    Truck newTruck(newCar);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

所以很明显 Truck.hpp 不能真正包含 Car.hpp,因为 CAR_HPP 已经定义。另外,Truck.hpp 不能转发声明,class Car;因为Truck(Car data)...需要完整类型,而转发声明的类不是完整类型。

看起来这很相似:前向声明被忽略?但没有答案。

本主题声明不要相互包含标题。前向声明和包含

我会尽量避免这种情况,但我怎样才能实现一辆可以接收卡车并正确转换的汽车以及一辆可以接收汽车并正确转换的卡车?

有没有一种方法,我可以使用: operator Car() { ... }operator Truck() { ... },使得汽车可以反之亦然铸造成一个卡车和副?

Bat*_*eba 5

在声明中

int ConvertFromTruck(Truck data)

Truck需要是一个完整的类型,这意味着类定义Truck必须对编译器可用。这就是你的问题。

幸运的是有一个解决方案:通过Truckconst参考:

int ConvertFromTruck(const Truck& data)

这里编译器只需要一个不完整的类型 for Truck,和一个前向类声明而不是#includewill 就足够了。这在运行时也非常优越,因为您没有Truck在函数运行时获取 的值副本(尽管编译器可能会优化该副本)。

对构造函数(即Car(const Truck& data))和Truck类执行相同的操作。

请注意,我使用const引用而不是非const引用有两个原因(i)您希望能够修改传递的对象,以及(ii)匿名临时对象可以绑定到const引用。