Pergunta

I have classes like this:

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

I've got a whole lot of functions that take ParkingLotBuilding. Let's say someone (me) derives from ParkingLot and 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?
}

I've got functions I don't control that are like this:

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

If I pass a DerivedParkingLotBuilding object to that function how do I make it so that it calls DerivedParkingLot::something() to return false? Is that possible? Sorry if I didn't explain this right I'm not sure how to ask about the problem. Thanks

Foi útil?

Solução

As JohnSmith pointed out, you can't override data members, just member functions. Since ParkingLotBuilding contains ParkingLot values, and not ParkingLot pointers or references, they can't be used polymorphically, even in DerivedParkingLot. (That's just how C++ works: only pointers and references can have a dynamic type.)

That means that if you can't change the ParkingLotBuilding class (or the CheckBuilding function), then you're stuck. There is no deriving you can do that will get the CheckBuilding function to operate on a DerivedParkingLot object.

The moral of this story is that classes must be designed for inheritance from the beginning.

Outras dicas

In fact you just to call the DerivedParkingLot function from a ParkingLot instance ?

Your code already did it by specifiying the something method as virtual, it will automaticaly search for the lowest method in his inherited tree.

A simple way to test it is to implement the something method in ParkingLot and DerivedParkingLot, put different message in each and check it

One way you might be able to approach this is by making ParkingLot a template class.

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

Then when creating a ParkingLotBuilding, you could use these types:

ParkingLotBuilding<ParkingLot>
ParkingLotBuilding<DerivedParkingLot>

Also if you don't like templating all the time and want to just use ParkingLotBuilding and DerivedParkingLotBuilding, you could rename the class to something like Building and use typedefs:

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

This approach isn't exactly inheritance between the ParkingLotBuilding types (and may not be the best approach - I've never seen this before), but it might do what you need.

In your example, Floor1 has no way of knowing whether it was instantiated inside of ParkingLotBuilding or DerivedParkingLotBuilding.

You could use RTTI to deal with this something like:

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

Not exactly the best was of doing this though, as pointed out above.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top