C++派生类用另一个派生类覆盖基类的成员?

Posted

技术标签:

【中文标题】C++派生类用另一个派生类覆盖基类的成员?【英文标题】:C++ Derived class overriding member of base class with another derived class? 【发布时间】:2013-08-22 21:32:04 【问题描述】:

我有这样的课程:

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 对象传递给该函数,我该如何让它调用 DerivedParkingLot::something() 返回 false?那可能吗?抱歉,如果我没有正确解释这个问题,我不知道如何询问这个问题。谢谢

【问题讨论】:

你不能覆盖成员,只能覆盖方法 补充一下 JohnSmith 所说的:由于 ParkingLotBuilding 包含 ParkingLot 值,而不是 ParkingLot 指针或引用,因此它们不能多态使用,即使在 DerivedParkingLot 中也是如此。 @zindorsky 我认为这是正确的答案。如果您或 John 想将其作为答案提交并进行解释,我会将其标记为正确。 【参考方案1】:

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

这意味着如果您无法更改 ParkingLotBuilding 类(或 CheckBuilding 函数),那么您将陷入困境。没有任何推导可以让CheckBuilding 函数对DerivedParkingLot 对象进行操作。

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

【讨论】:

【参考方案2】:

实际上你只是从一个 ParkingLot 实例调用 DerivedParkingLot 函数?

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

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

【讨论】:

【参考方案3】:

您可能能够解决此问题的一种方法是将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 类型之间的继承(并且可能不是最好的方法 - 我以前从未见过这种方法),但它可能会满足您的需求。

【讨论】:

【参考方案4】:

在您的示例中,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
    

正如上面所指出的那样,这样做并不是最好的。

【讨论】:

以上是关于C++派生类用另一个派生类覆盖基类的成员?的主要内容,如果未能解决你的问题,请参考以下文章

详解C++中基类与派生类的转换以及虚基类

关于C++基类与派生类

通过基类指针C++访问派生类的成员

C++中的基类和派生类

C++基类和派生类的构造函数

继承和派生