tags:

views:

132

answers:

5

Consider the following set of classes/Interfaces:

class IFish{
public:
virtual void eat() = 0;
}

class IFriendly{
public:
virtual void protect() = 0;
}

class IAggresive{
public:
virtual void attack(Point inDest) = 0;
}

class CDolphin : public IFish, IFriendly{
eat...
protect....
}

class CShark : public IFish, IAggresive{
eat....
attack...
}

Now I am having the following class

void CDiver
{

Void shouldRunAway(IFish* fish)
{
//???
}

}

My question is , can "shouldRunAway" extract from the fish argument whether it is an IAggresive or IFreindly (if it is any of these at all...) is there some kind of casting that can help out?

+3  A: 

Take a look at dynamic_cast.

Drakosha
I know what dynamic cast is. the thing is , As far as i know , Dynamic_cast only allow you to cast from base-class to sub-class. In our case IFriendly and IAggresive are not sub-classes of IFish, can you clarify your answer regarding to this point? thanks!
Look at answer by kitchen:void shouldRunAway( IFish *fish ) { if ( dynamic_cast<IAggressive *>( fish ) != NULL ) { std::cout << "Run away!\n"; } else { std::cout << "Don't run away.\n"; } }
Drakosha
yossi1981: if you run the code I posted, you will see that it does exactly what you've asked for.
kitchen
+1  A: 

The interfaces define what a class does, and not what it is. You should not use them as a "Is a" relation. In your case it would be better to define a IsDangerous() method in the IFish interface.

Casting in this case is possible in C++, but it will be bad design.

Dani van der Meer
It would be easy to think of an example where the class implements several interfaces for what it "does", nothing to do with what it "is", and then the question would be quite valid. Nor is necessarily bad design to want to allow some aspects of the relationship between two pieces of code to be optional and to avoid cluttering up the unrelated code. This is especially important if you're implementing a plugin system that can be extended by dropping in new DLLs (Windows) or shared libraries (Unix).
Daniel Earwicker
A: 

if this were Java, you could do:

if( fish instanceof IAggressive )
    runAway();

Perhaps there is some C++ equivalent? I've heard a lot about RTTI.. will that help?

jrh

Here Be Wolves
+4  A: 

Expanding on what Drakosha posted, you would dynamic_cast the IFish pointer into an IAggressive pointer and check if it is NULL or not. Like this;

#include <iostream>

class IFish {
public:
    virtual void eat() = 0;
};

class IFriendly {
public:
    virtual void protect() = 0;
};

class IAggressive {
public:
    virtual void attack() = 0;
};

class Dolphin : public IFish, public IFriendly {
public:
    virtual void eat() {
     std::cout << "Dolphin::eat()\n";
    }

    virtual void protect() {
     std::cout << "Dolphin::protect()\n";
    }
};

class Shark : public IFish, public IAggressive {
public:
    virtual void eat() {
     std::cout << "Shark::eat()\n";
    }

    virtual void attack() {
     std::cout << "Shark::attack()\n";
    }
};

class Diver {
public:
    void shouldRunAway( IFish *fish ) {
     if ( dynamic_cast<IAggressive *>( fish ) != NULL ) {
      std::cout << "Run away!\n";
     } else {
      std::cout << "Don't run away.\n";
     }
    }
};

int main( int argc, char *argv[] ) {
    Dolphin dolphin;
    Shark shark;
    Diver diver;

    diver.shouldRunAway( &dolphin );
    diver.shouldRunAway( &shark );

    return 0;
}
kitchen
+1  A: 

You could use the Visitor pattern if you don't care for dynamic_cast

#include <iostream>

class Diver;

class IFish {
public:
    virtual void eat() = 0;
    virtual void visit(Diver*) = 0;
};

class IFriendly {
public:
    virtual void protect() = 0;
};

class IAggressive {
public:
    virtual void attack() = 0;
};

class Diver {
public:
    void shouldRunAway( IFish *fish ) {
        fish->visit(this);
    }

    void runAway()
    {
        std::cout << "Run away!\n";
    }

    void dontRunAway()
    {
        std::cout << "Don't run away!\n";
    }
};

class Dolphin : public IFish, public IFriendly {
public:
    virtual void eat() {
        std::cout << "Dolphin::eat()\n";
    }

    virtual void protect() {
        std::cout << "Dolphin::protect()\n";
    }

    virtual void visit(Diver* diver)
    {
        diver->dontRunAway();
    }
};

class Shark : public IFish, public IAggressive {
public:
    virtual void eat() {
        std::cout << "Shark::eat()\n";
    }

    virtual void attack() {
        std::cout << "Shark::attack()\n";
    }

    virtual void visit(Diver* diver)
    {
        diver->runAway();
    }
};

int main( int argc, char *argv[] ) {
    Dolphin dolphin;
    Shark shark;
    Diver diver;

    diver.shouldRunAway( &dolphin );
    diver.shouldRunAway( &shark );

    return 0;
}
Rimo