C ++ Mutual头包含和前向声明

时间:2017-02-02 14:15:56

标签: c++ header-files forward-declaration

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

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)...需要完整类型,而前向声明的类不是完整类型。

看起来这是相似的:Forward declaration being ignored?但没有答案。

此主题声明不包含相互包含的标题。 Forward Declarations and Includes

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

有没有办法可以使用: operator Car() { ... }operator Truck() { ... }以便可以将汽车装入卡车,反之亦然?

1 个答案:

答案 0 :(得分:4)

在声明中

int ConvertFromTruck(Truck data)

Truck需要是完整的类型,这意味着编译器必须可以使用Truck的类定义。而且存在你的问题。

幸运的是有一个解决方案:通过Truck引用传递const

int ConvertFromTruck(const Truck& data)

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

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

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