C++派生类用另一个派生类重写基类的成员

C++ Derived class overriding member of base class with another derived class?

本文关键字:派生 成员 基类 另一个 C++ 重写      更新时间:2023-10-16

我有这样的类:

class ParkingLot
{
public:
    int spaces;
    virtual bool something() { return true; }
}
class ParkingLotBuilding
{
public:
    ParkingLot Floor1, Floor2;
}

我有很多功能需要ParkingLotBuilding。假设有人(我)源自ParkingLot和ParkingLotBuilding:

class DerivedParkingLot : public ParkingLot
{
public:
    virtual bool something() { return false; }
}
class DerivedParkingLotBuilding : public ParkingLotBuilding
{
public:
    // how can I make it so that Floor1 and Floor2 are for DerivedParkingLot?
}

我有一些无法控制的功能,它们是这样的:

CheckBuilding( ParkingLotBuilding &building )
{
    if(building.Floor1.something() == true)
    // error
}

如果我将DerivedParkingLotBuilding对象传递给该函数,我该如何使其调用DerivedPackingLot::something()返回false?这可能吗?对不起,如果我没有正确解释,我不知道该怎么问这个问题。感谢

正如JohnSmith所指出的,不能覆盖数据成员,只能覆盖成员函数。由于ParkingLotBuilding包含ParkingLot值,而不是ParkingLot指针或引用,因此即使在DerivedParkingLot中,它们也不能以多态方式使用。(这就是C++的工作方式:只有指针和引用才能具有动态类型。)

这意味着,如果不能更改ParkingLotBuilding类(或CheckBuilding函数),那么就会陷入困境。没有任何派生可以让CheckBuilding函数对DerivedParkingLot对象进行操作。

这个故事的寓意是,类必须从一开始就为继承而设计。

实际上,您只是想从ParkingLot实例调用DerivedParkingLot函数吗?

您的代码已经通过将something方法指定为虚拟方法来实现了这一点,它将自动搜索他继承的树中最低的方法。

测试它的一个简单方法是在ParkingLot和DerivedParkingLot中实现something方法,在每个方法中放入不同的消息并检查

实现这一点的一种方法是将ParkingLot作为模板类。

template<typename T>
class ParkingLotBuilding
{
public:
    T Floor1, Floor2;
}

然后在创建ParkingLotBuilding时,可以使用以下类型:

ParkingLotBuilding<ParkingLot>
ParkingLotBuilding<DerivedParkingLot>

此外,如果您不喜欢一直使用模板,只想使用ParkingLotBuildingDerivedParkingLotBuilding,则可以将类重命名为类似Building的类,并使用typedefs:

typedef Building<ParkingLot> ParkingLotBuilding
typedef Building<DerivedParkingLot> DerivedParkingLotBuilding

这种方法并不完全是ParkingLotBuilding类型之间的继承(可能不是最好的方法——我以前从未见过这种方法),但它可能会满足您的需要。

在您的示例中,Floor1无法知道它是在ParkingLotBuilding还是DerivedParkingLotBuilding内部实例化的。

你可以使用RTTI来处理这个问题,比如:

CheckBuilding (ParkingLotBuilding *building)
{
    if (dynamic_cast<DerivedParkingLogBuilding*>(building))
    {
        // Floor is in a derived parking log building
    }
    else
    {
        // Floor is in a parking lot building
    }
}

不过,正如上文所指出的,这样做并不完全是最好的。