开发者

Strange problem with dynamic cast C++ [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center. Closed 11 years ago.

I'm just new to C++, and doing a small project which i开发者_JAVA技巧mplementing some inheritance. It can basically be summarized below:

//.h file
class Food{
public:
 Food();
 virtual ~Food();
};

class Animal{
public:
 Animal();
 virtual ~Animal();
 virtual void eat( Food f);
};

class Meat : public Food{
public:
 Meat();
 ~Meat();
};

class Vegetable : public Food{
public:
 Vegetable();
 ~Vegetable();
};

class Carnivore : public Animal{
public:
 Carnivore();
 ~Carnivore();
 void eat(Food f);
};

//.cpp file

Food::Food()
{
do something;
}

Food:~Food()
{
do something;
}

Animal::Animal()
{
do something;
}

Animal::~Animal()
{
do something;
}

Meat::Meat()
{
do something;
}

Meat::~Meat()
{
do something;
}

Vegetable::Vegetable()
{
do something;
}

Vegetable::~Vegetable()
{
do something;
}

Carnivore::Carnivore()
{
do something;
}

Carnivore::~Carnivore()
{
do something;
}

void Carnivore::eat(Food f)
{
 Meat* m = dynamic_cast<Meat*>(&f); 
 if(m != 0) cout << "can eat\n";
 else cout << "can not eat\n";
}

//main.cpp

int main()
{
Animal* a;
Food* f;

Meat m;
Vegetable v;
Carnivore c;

a = &c;
f = &v;
a->eat(*f);
f = &m;
a->eat(*f);


return 1;
}

And the output:

can not eat
can not eat


When you have a function like this:

void Carnivore::eat(Food f)

it takes its parameter by value. That means a copy of the provided object is made.

In this case, you're specifying a type Food, so you end up with a Food object. No magic polymorphism, nothing. Just a bog-standard Food object.

This is known as slicing; please go ahead and look up this term, as there is loads of stuff about it on the web.

In short, though, you can maintain the use of polymorphism by accepting a reference to the existing polymorphic object:

void Carnivore::eat(Food& f)

Also, next time please post a minimal testcase. That's a huge snippet of code!

Good luck with your studies.


You're passing food by value into the eating function. For polymorphism to work you need to pass either by reference or by pointer:

(by pointer:)

void Carnivore::eat(Food* f)
{
 Meat* m = dynamic_cast<Meat*>(f); 
 if(m != 0) cout << "can eat\n";
 else cout << "can not eat\n";
}


This is what's known as the "slicing problem". Your functions are taking a copy of the object you pass. The copy is being generated by the copy constructor for the base type, and any specialization you've done for the derived class is lost.


Object slicing is what causing the problem in your implementation.

Your eat() function should take either reference to Food or pointer to Food as explained below:

virtual void eat(Food & f);

//usage
Meat meat;
animal.eat(meat);

Or

virtual void eat(Food * pf);

//usage
Meat meat;
animal.eat(&meat); //note &


C++'s run-time polymorphism (aka virtual function calls / virtual dispatch) requires that the functions be called via a pointer or reference to a base class. Here, your eat function takes a Food argument by value... which copies or slices the part of the *f value and creates a new Food object. Such objects can never be casted by dynamic_cast<Meat*>, because the Meat part has been chopped off. Just change to Carnivore::eat(const Food& f) and it will work....

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜