C++ Производный класс переопределяет член базового класса другим производным классом?

У меня есть такие классы:

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? Это возможно? Извините, если я не объяснил это правильно, я не уверен, как спросить о проблеме. Спасибо


person user2672807    schedule 22.08.2013    source источник
comment
вы не можете переопределить членов, только методы   -  person UnknownError1337    schedule 23.08.2013
comment
В дополнение к тому, что сказал Джон Смит: поскольку ParkingLotBuilding содержит ParkingLot значений, а не ParkingLot указателей или ссылок, их нельзя использовать полиморфно, даже в DerivedParkingLot.   -  person zindorsky    schedule 23.08.2013
comment
@zindorsky Я думаю, что это правильный ответ. Если вы или Джон хотите представить это как ответ и объяснить, я отмечу это как правильное.   -  person user2672807    schedule 23.08.2013


Ответы (4)


Как указал JohnSmith, вы не можете переопределять элементы данных, только функции-члены. Поскольку ParkingLotBuilding содержит ParkingLot значений, а не ParkingLot указателей или ссылок, их нельзя использовать полиморфно, даже в DerivedParkingLot. (Именно так работает C++: только указатели и ссылки могут иметь динамический тип.)

Это означает, что если вы не можете изменить класс ParkingLotBuilding (или функцию CheckBuilding), то вы застряли. Вы не можете сделать вывод, который заставит функцию CheckBuilding работать с объектом DerivedParkingLot.

Мораль этой истории в том, что классы должны быть спроектированы для наследования с самого начала.

person zindorsky    schedule 23.08.2013

На самом деле вы просто вызываете функцию DerivedParkingLot из экземпляра ParkingLot?

Ваш код уже сделал это, указав метод something как виртуальный, он будет автоматически искать самый низкий метод в его унаследованном дереве.

Простой способ проверить это — реализовать метод something в ParkingLot и DerivedParkingLot, поместить в каждый из них разные сообщения и проверить их.

person Joe Bow    schedule 22.08.2013

Один из способов приблизиться к этому — сделать ParkingLot классом-шаблоном.

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

Затем при создании ParkingLotBuilding вы можете использовать следующие типы:

ParkingLotBuilding<ParkingLot>
ParkingLotBuilding<DerivedParkingLot>

Кроме того, если вам не нравится постоянно использовать шаблоны и вы хотите просто использовать ParkingLotBuilding и DerivedParkingLotBuilding, вы можете переименовать класс во что-то вроде Building и использовать typedefs:

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

Этот подход не совсем наследование между типами ParkingLotBuilding (и, возможно, не лучший подход — я никогда раньше такого не видел), но он может делать то, что вам нужно.

person Michael Oliver    schedule 22.08.2013

В вашем примере 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
    }
}

Однако, как указано выше, это было не лучшим решением.

person Chris    schedule 23.08.2013