Subclasses as arguments? - c++

I am attempting to create something like this:
class food
{
public:
void EAT(); //Whatever happens...
int bitesLeft //This is decreased by one each time you eat the food
};
class cheese: public food
{
public:
void EAT(); //Some overloaded form of the "eat" command...
};
Is there a way to create one of each at runtime, and have a function that can take either one as arguments without screwing up the bitesLeft variable of each one?

I'm assuming you want something like:
function doStuff(food * f) {
f->EAT();
}
And you want this to call the specialised EAT if a cheese is passed in, or the non-specialised form if a food is passed in. In this case, you need a virtual function:
class food {
public:
virtual void EAT();
virtual ~food(); // Any class being used polymorphically should have
// a virtual destructor
}
class cheese : public food {
public:
virtual void EAT();
}
I'm not exactly sure what you mean by 'without screwing up the bytesLeft variable. This is a public data member, so it's possible for any code to modify the value of the variable in ways you weren't expecting. This includes code in the cheese class, but also code that's not in either of the classes.
If you want to prevent code in the cheese.EAT method from modifying the bitesLeft member then you should declare it as private in the base class.

Yes, there is:
void myfunc(food* f)
{
f->EAT();
}
int main()
{
food f;
cheese c;
myfunc(&f);
myfunc(&c);
return 0;
}
However, for this to work, you need to declare EAT() as virtual in the food class, as in virtual void EAT();. Also, you probably want to declare bitesLeft as protected, so that only the class itself as well as the subclasses can access it.

The member variables of two objects are separate. This code works as you expect:
void AFunction( food& x ) {
x.EAT();
}
food a;
a.bitesLeft = 10;
cheese b;
b.bitesLeft = 5;
AFunction(a); // a.bitesLeft --> 9
AFunction(b); // b.bitesLeft --> 4

Related

Preferred way to understand object type at runtime

Consider I have a Plant class that has derived Fruit and Vegetable classes, and Fruit class has some more derived classes, like Orange and Apple, while Vegetable has derived Potato and Tomato. Assume, Plant has Plant::onConsume()=0; method:
class Plant
{
public:
virtual void onConsume(void)=0;
};
class Fruit:public Plant
{
};
class Orange:public Fruit
{
void onConsume(void)
{
// Do something specific here
}
};
class Apple:public Fruit
{
void onConsume(void)
{
// Do something specific here
}
};
class Vegetable:public Plant
{
};
class Potato:public Vegetable
{
void onConsume(void)
{
// Do something specific here
}
};
class Tomato:public Vegetable
{
void onConsume(void)
{
// Do something specific here
}
};
class Consumer
{
public:
void consume(Plant &p)
{
p.onConsume();
// Specific actions depending on actual p type here
// like send REST command to the remote host for Orange
// or draw a red square on the screen for Tomato
}
};
Suppose, I have a Consumer class with Consumer::consume(Plant) method. This "consume" method should perform different actions for different "Plants" instances/types, among calling Plant::onConsume() for any of "Plants". These action ain't directly related to the Plant class, require a lot of different additional actions and parameters, could literally be completely arbitrary, so cannot be implemented inside onConsume method.
What is the preferred method to implement this? As I understand, it is possible to implement some "Plant::getPlantType()=0" method, that would return plant type, but in this case I'm not sure what should it return. In case the returned value would be an enum, I'd need to change this enum each time I add a new derived class. And in any case, there's no control that multiple derived classes could return the same value.
Also, I'm aware there's a dynamic_cast conversion that returns nullptr if conversion could not be made, and typeid() operator that returns std::typeinfo (even with typeinfo::name()), which could be used in the switch() (it's just great for my case). But I'm afraid it could significally slow down the execution and make code heavier.
So, my question is, what is the preferred way in C++ to do that? maybe I just forgot about some simpler way to implement that?
A little update. Thank you for your explanations about inheritance, encapsulation etc! I supposed it's clear from my question, but it is not, I am sorry about that. So, please think about it, like I don't have an access to the whole Plant sources hierarchy, just need to implement this Consumer::onConsume(Plant). So I cannot add new specific methods in it. Or, also, it could be considered as a Plants library, that I have to write once, and make it usable for other devs. So, I could divide use cases/functionality into two parts: one that implemented "per class" in the Plant::onConsume() method, and second that is unknown yet and will differ depending on usage.
One option would be the visitor pattern, but this requires one function per type in some class. Basically you create a base class PlantVisitor with one Visit function per object type and pass add a virtual method to Plant that receives a PlantVisitor object and calls the corresponding function of the visitor passing itself as parameter:
class PlantVisitor
{
public:
virtual void Visit(Orange& orange) = 0;
virtual void Visit(Tomato& tomato) = 0;
...
};
class Plant
{
public:
virtual void Accept(PlantVisitor& visitor) = 0;
};
class Orange : public Plant
{
public:
void Accept(PlantVisitor& visitor) override
{
visitor.Visit(*this);
}
};
class Tomato : public Plant
{
public:
void Accept(PlantVisitor& visitor) override
{
visitor.Visit(*this);
}
};
This would allow you to do something like this:
class TypePrintVisitor : public PlantVisitor
{
public:
void Visit(Orange& orange) override
{
std::cout << "Orange\n";
}
void Visit(Tomato& tomato) override
{
std::cout << "Tomato\n";
}
};
std::vector<std::unique_ptr<Plant>> plants;
plants.emplace_back(std::make_unique<Orange>());
plants.emplace_back(std::make_unique<Tomato>());
TypePrintVisitor visitor;
for (size_t i = 0; i != plants.size(); ++i)
{
std::cout << "plant " << (i+1) << " is a ";
plants[i]->Accept(visitor);
}
Not sure the need for this does not indicate a design inefficiency though.
Btw: If you've got multiple visitors and do not necessarily want to implement logic for every single type in all of them, you could add default implementations in PlantVisitor that call the function for the supertype instead of specifying pure virtual functions.
Polymorphism is all about not having to know about a specific type. Usually your design is flawed if you discover having to detect a specific type explicitly.
At very first:
void Consumer::consume(Plant p)
does not work as intended! The Plant object is accepted by value, i. e. its bytes are copied one by one; however, only those of the Plant type, any others (those of derived types) are ignored and get lost within consume function – this is called object slicing.
Polymorphism only works with references or pointers.
Now assume you want to do something like the following (incomplete code!):
void Consumer::consume(Plant& p) // must be reference or pointer!
{
p.onConsume();
generalCode1();
if(/* p is apple */)
{
appleSpecific();
}
else if(/* p is orange */)
{
orangeSpecific();
}
generalCode2();
}
You don't want to decide yourself upon type, you let the Plant class do the stuff for you, which means you extend its interface appropriately:
class Plant
{
public:
virtual void onConsume() = 0;
virtual void specific() = 0;
};
The code of the consume function will now be changed to:
void Consumer::consume(Plant const& p) // must be reference or pointer!
{
p.onConsume();
generalCode1();
p.specific();
generalCode2();
}
You'll do so at any place you need specific behaviour (and specific is just a demo name, chose one that describes nicely what the function actually is intended to do).
p.onConsume();
generalCode1();
p.specific1();
generalCode2();
p.specific2();
generalCode3();
p.specific3();
generalCode4();
// ...
Of course you need now to provide appropriate implementations in your derived classes:
class Orange:public Fruit
{
void onConsume() override
{ }
void specific() override
{
orangeSpecific();
}
};
class Apple:public Fruit
{
void onConsume() override
{ }
void specific() override
{
appleSpecific();
}
};
Note the addition of override keyword, which protects you from accidentally creating overloaded functions instead actually overwriting in case of signature mismatch. It helps you, too, to locate all places of necessary changes if you discover having to change the function signature in the base class.

How to access derived class member function using Base class function?

I am trying to design a parking system (Low-level Design )
Some classes behave like this.
class Vehicle
{
public:
int entryTime;
int exitTime;
virtual void leaveParking(Vehicle*);
virtual int getChargePerHr();
//virtual void getChargePerHr() = 0;
Vehicle() {}
};
class Car : public Vehicle
{
private :
int chargePerHr = 30;
public:
void leaveParking(Vehicle*);
int getChargePerHr();
Car(){}
};
class Bike : public Vehicle
{
private :
int chargePerHr = 10;
public:
void leaveParking(Vehicle*);
int getChargePerHr();
Bike(){}
}
void Vehicle ::leaveParking(Vehicle* v)
{
int pay = v-> // Here expecting Car class member function getChargePerHr() should come
//so that I can access private member chargePerHr of car class.
// But I am not able to access the Car class member function here.
}
int main()
{
Car c1; // assume Car c1 has already parked.
Vehicle v;
Vehicle* vptr = new Vehicle();
vptr = new Car();
c1.leaveParking(vptr); // Car c1 wants to leave the parking place
}
I want to access getChargePerHr() of Car class using Base class Vehicle member function.
I tried with pure virtual function but still could not make it.
Could anyone help me?
Problem
Here:
void Vehicle::leaveParking(Vehicle* v)
{
...
}
You're not able to access Car::getChargePerHr() because v is a Vehicle not a Car.
Clearly you're attempting to achieve polymorphism since it appears you want derived classes of Vehicle to perform the same actions when they leave parking.
Solution
Declare Vehicle::getChargePerHr() as pure virtual (or virtual if you want a default implementation)
Provide implementations of getChargePerHr() in your derived classes
Implement Vehicle::leaveParking() using just the methods you've defined in Vehicle
At runtime, the virtual table will resolve overrides and call the correct derived implementation.
Other Issues
You are inheriting from Vehicle without declaring its destructor virtual. This means if any child classes need to perform clean-up, their destructors won't be called.
You're missing a semicolon after the Bike class declaration.
If every Vehicle does the same thing when leaving parking, it doesn't make sense to have leaveParking() be virtual—you make a member function virtual if you want it to be able to be overridden by child classes.
Vehicle::leaveParking() should probably not be taking another Vehicle as a parameter. The function acts on the vehicle itself, not on a different one.
If your constructor is empty, it's better to leave it out of the class declaration since it can confuse others who might read your code.
And many more issues. I suggest you take aalimian's advice to read up on C/C++. Your code shows many misunderstandings.
Code
Putting everything together, here's an example:
class Vehicle
{
public:
int entryTime;
int exitTime;
virtual ~Vehicle() = default;
void leaveParking();
virtual int getChargePerHr() = 0;
};
void Vehicle::leaveParking()
{
// This will call a derived class's implementation
int pay = getChargePerHr();
// Do more vehicle stuff
}
class Car : public Vehicle
{
private:
int chargePerHr = 30;
public:
int getChargePerHr() override;
};
int Car::getChargePerHr()
{
return chargePerHr;
}
class Bike : public Vehicle
{
private:
int chargePerHr = 10;
public:
int getChargePerHr() override;
};
int Bike::getChargePerHr()
{
return chargePerHr;
}
You can see this in action here.

virtual methods C++

I'm facing the following problem.
I implement parent Class - Vehicle, it has some derived classes, one of them - FastVehicle.
In the program I need to store a Vector of Vehicle* pointers. the pointers may point to Vehicle objects or to FastVehicle objects as well.
1) I want to be able to call the method print() for every object in the vector.
The problem is that in case of FastVehicle I also want to tranfer a parameter to the function,
I need to call a function with signature:
void print(int a)
I know a little bit about the virtual function mechanism, but according to my knowledge it works only if both functions have the same signature.
I would like to hear suggestions, about how to work it out.
2) In addition in the derived class FastVehicle has some unique function that it doesn't share with the parent class Vehicle.
It performs a task that should be performed only for FastVehicle objects.
What is the cleanest way to achieve this?
I thought maybe to implement "empty" virtual function in the parent class Vehicle and implement the "real" task inside an overriding method of FastVehicle
Maybe someone can suggest a better solution.
thanks
You can always use a dynamic_cast to cast Vehicle to FastVehicle. It returns NULL if Vehicle is not FastVehicle. It depends on your use situation if you should really do this.
for(Vehicle* vehicle : vehicleVector)
{
FastVehicle* fastVehicle = dynamic_cast<FastVehicle*>(vehicle);
if(fastVehicle)
{
fastVehicle->print(1337);
fastVehicle->somethingElse();
}
else
{
vehicle->print();
}
}
Full example available here: https://ideone.com/69n6Jb
Most likely you have to rethink why you need a parameter for FastVehicle, but not for anything other type of Vehicle. That to me is an indication of bad design.
Just declare print(int) in the base class, override it, but in the classes where you don't need the int, just disregard it.
The pragmatic solutions are:
Pass the int a parameter to the virtual print method but ignore it in Vehicle and only use it in FastVehicle
As you suggest, simply add an "empty" virtual function to the base class that is a no-op in Vehicle and is only implemented in FastVehicle
E.g:
struct Vehicle {
virtual ~Vehicle(){}
virtual void print(int /*a*/) const { std::cout << "Vehicle print\n"; }
virtual void somethingElse() { /* no-op */ }
};
struct FastVehicle : Vehicle {
void print(int a) const override {std::cout << "FastVehicle print " << a << "\n";}
void somethingElse() override { std::cout << "Something else!\n"; }
};
for (auto vehicle : vehicles) {
vehicle->print(512);
vehicle->somethingElse();
}
Live demo
Perhaps you could refactor with an abstract vehicleI:
struct vehicleI {
....
virtual void print(int) = 0;
}
and then your vehicle:
struct vehicle : vehicleI {
....
void print(int i = 0);
}
and your fastVehicle as:
struct fastvehicle: vehicleI {
....
void print(int);
}
if you want to properly use a dynamic call to a Vehicle interface, you need to define a common interface.
If you need to specify a parameter in case of FastVehicle but not in the case of FastVehicle, that's not an interface anymore.
You have two solutions:
Default parameter
struct Vehicle
{
virtual void print(int a=0) {};
};
struct FastVehicle : public Vehicle
{
void print(int a=0) override {};
};
now you can call both with or without a parameter.
Second option:
struct Vehicle
{
virtual void print() {};
};
struct FastVehicle : public Vehicle
{
void print() override {};
void setA(int a) { _a = a; }
_a{};
};
Now you can set your 'a' variable through another method, but not when you access the object through Vehicle's interface.

c++ overriding a function only for a specific instance

I was wondering whether there's a way to override a function for a specific instance only. For ex,
class A
{
public:
...
void update();
...
}
int main()
{
...
A *first_instance = new A();
// I want this to have a specific update() function.
// ex. void update() { functionA(); functionB(); ... }
A *second_instance = new A();
// I want this to have a different update() function than the above one.
// ex. void update() { functionZ(); functionY(); ...}
A *third_instance = new A();
// ....so on.
...
}
Is there a way to achieve this?
I think virtual function is just what you want, with virtual function, different instances of the same type can have different functions, but you need to inherit the base class. for example
class A
{
public:
...
virtual void update()
{
std::cout << "Class A\n";
}
...
};
class B: public A
{
public:
virtual void update()
{
std::cout << "Class B\n";
}
};
class C: public A
{
public:
virtual void update()
{
std::cout << "Class C\n";
}
};
int main()
{
...
A *first_instance = new A();
// I want this to have a specific update() function.
// ex. void update() { functionA(); functionB(); ... }
A *second_instance = new B();
// I want this to have a different update() function than the above one.
// ex. void update() { functionZ(); functionY(); ...}
A *third_instance = new C();
// ....so on.
...
}
each instance in the above code will bind different update functions.
Besides, you can also use function pointer to implement your requirement, but it is not recommended. For example
class A
{
public:
A(void(*u)())
{
this->update = u;
}
...
void (*update)();
};
void a_update()
{
std::cout << "update A\n";
}
void b_update()
{
std::cout << "update B\n";
}
void c_update()
{
std::cout << "update C\n";
}
int main()
{
...
A first_instance(a_update);
// I want this to have a specific update() function.
// ex. void update() { functionA(); functionB(); ... }
A second_instance(b_update);
// I want this to have a different update() function than the above one.
// ex. void update() { functionZ(); functionY(); ...}
A third_instance(c_update);
// ....so on.
...
}
Hope helps!
Hold a function in the class.
#include <iostream>
#include <functional>
using namespace std;
class Foo
{
public:
Foo(const function<void ()>& f) : func(f)
{
}
void callFunc()
{
func();
}
private:
function<void ()> func;
};
void printFoo() { cout<<"foo"<<endl; }
void printBar() { cout<<"bar"<<endl; }
int main()
{
Foo a(printFoo);
Foo b(printBar);
a.callFunc();
b.callFunc();
}
You may have noticed that the end brace of a class is often followed by a semicolon, whereas the end braces of functions, while loops etc don't. There's a reason for this, which relates to a feature of struct in C. Because a class is almost identical to a struct, this feature exists for C++ classes too.
Basically, a struct in C may declare a named instance instead of (or as well as) a named "type" (scare quotes because a struct type in C isn't a valid type name in itself). A C++ class can therefore do the same thing, though AFAIK there may be severe limitations on what else that class can do.
I'm not in a position to check at the moment, and it's certainly not something I remember using, but that may mean you can declare a named class instance inheriting from a base class without giving it a class name. There will still be a derived type, but it will be anonymous.
If valid at all, it should look something like...
class : public baseclass // note - no derived class name
{
public:
virtual funcname ()
{
...
}
} instancename;
Personally, even if this is valid, I'd avoid using it for a number of reasons. For example, the lack of a class name means that it's not possible to define member functions separately. That means that the whole class declaration and definition must go where you want the instance declared - a lot of clutter to drop in the middle of a function, or even in a list of global variables.
With no class name, there's presumably no way to declare a constructor or destructor. And if you have non-default constructors from the base class, AFAIK there's no way to specify constructor parameters with this.
And as I said, I haven't checked this - that syntax may well be illegal as well as ugly.
Some more practical approaches to varying behaviour per-instance include...
Using dependency injection - e.g. providing a function pointer or class instance (or lambda) for some part of the behavior as a constructor parameter.
Using a template class - effectively compile-time dependency injection, with the dependency provided as a function parameter to the template.
I think it will be the best if you'll tell us why do you need to override a function for a specific instance.
But here's another approach: Strategy pattern.
Your class need a member that represent some behaviour. So you're creating some abstract class that will be an interface for different behaviours, then you'll implement different behaviours in subclasses of that abstract class. So you can choose those behaviours for any object at any time.
class A;//forward declaration
class Updater
{
public:
virtual ~Updater() {};//don't forget about virtual destructor, though it's not needed in this case of class containing only one function
virtual void update(A&) = 0;
}
class SomeUpdater
{
public:
virtual void update(A & a);//concrete realisation of an update() method
}
class A
{
private:
Updater mUpdater;
public:
explicit A(Updater updater);//constructor takes an updater, let's pretend we want to choose a behaviour once for a lifetime of an object - at creation
void update()
{
mUpdater.update(this);
}
}
You can use local classes, yet, personally, I consider the "hold function in the class" approach mentioned in the other answer better. I'd recommend the following approach only if doFunc must access internals of your base class, which is not possible from a function held in a member variable:
class ABase {
public:
void Func () { this->doFunc (); }
private:
virtual void doFunc () = 0;
public:
virtual ~ABase () { }
};
ABase* makeFirstA () {
class MyA : public ABase {
virtual void doFunc () { std::cout << "First A"; }
};
return new MyA;
}
ABase* makeSecondA () {
class MyA : public ABase {
virtual void doFunc () { std::cout << "Second A"; }
};
return new MyA;
}
int main () {
std::shared_ptr<ABase> first (makeFirstA ());
std::shared_ptr<ABase> second (makeSecondA ());
first->Func ();
second->Func ();
}
From a design patterns point of view, the "local classes" approach implements the template method pattern, while the "hold a function(al) in a member variable" approach reflects the strategy pattern. Which one is more appropriate depends on what you need to achieve.

Special interaction between derived objects (i.e. mutiple dispatch)

So, I have a list of base class pointers:
list<Base*> stuff;
Then, at some point one of the objects will look through all other objects.
Base * obj = ...; // A pointer from the 'stuff'-list.
for (list<Base*>::iterator it = stuff.begin(); it != stuff.end(); it++)
{
if (obj == *it)
continue;
// Problem scenario is here
obj->interact(it);
}
What I want to achieve is that depending on what derived typeobj and *it are, they will interact differently with each other, i.e. DerivedA will destroy itself if it's interacting with DerivedB, but only if DerivedB has set the property bool c = true;. So something like:
struct Base
{
virtual void interact(Base * b); // is always called
};
struct DerivedA : public Base
{
virtual void interact(Base * b){} // is never called
virtual void interact(DerivedB * b) // is never called
{
if (b->c)
delete this;
}
};
struct DerivedB : public Base
{
bool c = false;
virtual void interact(Base * b){} // is never called
virtual void interact(DerivedA * a) // is never called
{
c = true;
}
};
// and many many more Derived classes with many many more specific behaviors.
At compile time, they are both Base-pointers and will not be able to call each other and expect the type to magically appear. If this was a one way relation, i.e. I knew what type of one of them, I could use the Visitor pattern. I believe I should use some kind of Mediator pattern but can't really figure out how since the mediator too will hold Base-pointers and thus it won't make a difference.
I haven't got a clue on how to continue... anyone?
Background:
I'm creating a game, this problem originates from the Room class who keeps track of it's contents, i.e. what GameObjects are currently in the room.
Sometimes, an object moves (for example, the player). The room will then loop over all objects that are on the soon-to-be-moved-upon floor tile (the loop above) and will check if the objects will interact with eachother.
For example, if it's a Troll the Player would want to hurt it. Or he would just like to hurt any Character (both Troll and Player are derived from Character) that originates from any another "team" (which can be accessed from the function getAlignment(), which all Characters implement).
If you can, grab a copy of "More Effective C++", and have a look at item #31 which is about implementing multiple dispatch, which is basically what you're looking for here. Meyers discusses several approaches to the problem and their various trade-offs. (He even uses a game as an example.)
Perhaps the best advice he gives, however, is to try and redesign your code to avoid requiring this facility. In the text, a non-member function approach is also explored, which has the added bonus of eliminating the question of to which object each function describing an interaction should belong.
I think your suggested idea (with the Base::interact) function is almost complete. It seems that the only missing part is this:
In your Base, you need to have all the interact overloads for the sub-types. Consider this extension to your Base structure:
struct DerivedA;
struct DerivedB;
struct Base
{
virtual void interact(Base * b); // *<->Base interaction
virtual void interact(DerivedA * da); // *<->DerivedA interaction
virtual void interact(DerivedB * db); // *<->DerivedB interaction
};
This is a painful thing about implementing double-dispatch in C++: if you add a new sub-type, you have to touch the base of the hierarchy.
you will need to implement all possible combinations of types interacting with each other as virtual functions on top of hierarchy.
Here's an example that tests all possible interactions:
#include<iostream>
void say(const char *s){std::cout<<s<<std::endl;}
struct DerivedA;
struct DerivedB;
struct Base{
virtual void interact(Base *b) = 0;
virtual void interactA(DerivedA *b) = 0;
virtual void interactB(DerivedB *b) = 0;
};
struct DerivedA : public Base
{
virtual void interact(Base *b){
b->interactA( this );
}
virtual void interactA(DerivedA *b){
say("A:A");
}
virtual void interactB(DerivedB *b){
say("A:B");
}
};
struct DerivedB:public Base{
virtual void interact(Base *b){
b->interactB( this );
}
virtual void interactA(DerivedA *b){
say("B:A");
}
virtual void interactB(DerivedB *b){
say("B:B");
}
};
void interact(Base *b1,Base *b2){
b1->interact( b2 );
}
main(){
Base *a = new DerivedA;
Base *b = new DerivedB();
interact(a,b);
interact(b,a);
interact(a,a);
interact(b,b);
}
First: Why do you use struct instead of class?
Second: If you use class instead of struct you could (must) do something like this:
class Base
{
virtual void interact(Base * b); // see the VIRTUAL word (explained down)
};
class DerivedA : public Base
{
virtual void interact(DerivedB * b)
{
if (b->c)
delete this;
}
};
class DerivedB : public Base
{
bool c = false;
virtual void interact(DerivedA * a)
{
c = true;
}
};
Using virtual keyword is wath you need (I guess). If you define a method as virtual you are telling "Hey! this maybe has been override someplace" so.. when you code this:
DerivedA* a = new DerivedA();
DerivedB* b = new DerivedB();
a.interact(b); // here instead of calling Base::interact(Base*) call the override method in DerivedA class (because is virtual)
EDIT:
Forget that answer.. (didn't see the comment of the virtual)
EDIT 2:
Please, see catwalk and Frerich Raabe answers.
Your interact() functions don't have the same signature: In the derived classes they should also be
virtual void interact(Base * b);
The virtual is optional, of course, but for clarity I'd put it in there.
To find out whether DerivedA::interact() should do something with it's parameter, you can implement another virtual functions in your base class:
virtual canDoX(Base * b);
virtual canDoY(Base * b);
Then in the derived implementations it could look like this:
// DerivedA
void interact(Base * b)
{
if (b->canDoX() && b->c)
delete this;
}
// DerivedB
void interact(Base * b)
{
if(b->canDoY())
c = true;
}
Update:
Since you liked Frerich Raabe's answer, let me explain why I think my approach is a bit better.
Following his advice, one has to create an interact() method for each derived class in the base and all other derived classes that can interact with a certain class.
With my solution one would have to add methods for certain properties, that can also be combined.
If you have a Troll it would return true in its canBeKilled() method. An apple canBeEaten() and a tasty wild animal canBeKilled() and then canBeEaten().
If you can combine the properties, you have to add fewer functions.
Furthermore: If the troll drank some elixir making it invulnerable for a period of time, it returns canBeKilled() == false and that's it. You don't have to check the isInvulnerable() flag in each other interacting class.
I think your problem is well discussed in
Scott Meyer's Effective C++ which is like as follows:
Rule : Don't try access array of derived class objects using base class pointer -->the result would be undefined.
I will give you an example of it:
struct Base{
virtual void print() { //in base }
virtual ~Base() {} //
}
struct Derived : public Base {
virtual void print(){ //in derived }
}
void foo(Base *pBase,int N)
{
for(int i=0; i<N ; i++)
pBase[i].print(); // result will be undefined......
}
int main()
{
Derived d[5];
foo(&d,5);
}
The reason for it such behaviour is that compiler find next elements at the jump of sizeof(Base) bytes....
I think you got my point....