I have four .cpp files, Animal, Cattle, Sheep, DrugAdmin
.
Animal
is parent class of Cattle
, and it has calcDose()
, which calculates the amount of dose. DrugAdmin
is main function.
The thing is, I want to use calcDose()
function differently (Cattle, Sheep) and no calcDose()
function is needed for Animal
class. However, every time I try to use calcDose()
, it automatically calls function in Animal
class even when I want to use under Cattle
class. This is the code I have done so far. (I've cut it down)
Animal.cpp
#include "Animal.h"
#include <string>
using namespace std;
Animal::Animal(int newid, double newweight, int yy, int mm, int dd, char newsex, vector<Treatment> trea开发者_开发百科tArray)
{
id = newid;
weight = newweight;
yy = yy;
mm = mm;
dd = dd;
accDose = 0;
sex = newsex;
}
double Animal::calcDose(){
return 0;
}
Cattle.cpp
#include "Cattle.h"
using namespace std;
Cattle::Cattle(int newid, double newweight, int yy, int mm, int dd,
char newsex, vector<Treatment> newtreatArray, string newcategory)
: Animal(newid, newweight, yy,mm,dd, newsex, newtreatArray)
{
id = newid;
weight = newweight;
accDose = 0;
sex = newsex;
Cattle::category = newcategory;
}
Cattle::~Cattle(){}
double Cattle::calcDose(){
if(getDaysDifference() < 90 || getCategory() == "Meat"){
accDose = 0;
return accDose;
}
else if(getCategory() == "Dairy"){
if (weight < 250 || accDose > 200){
accDose = 0;
}
else{
accDose = weight * 0.013 + 46;
}
return accDose;
}
else if(getCategory() == "Breeding"){
if (weight < 250 || accDose > 250){
accDose = 0;
}
else{
accDose = weight * 0.021 + 81;
}
return accDose;
}
else
{
//cout << "It is not valid category" << endl;
}
}
Sheep class is pretty much same but the contents of calcDose()
DrugAdmin.cpp
#include "DrugAdmin.h"
using namespace std;
vector<Animal*> vec_Animal;
void addAnimal(){
int select=0;
int id;
double weight;
int yy;
int mm;
int dd;
char sex;
string category;
vector<Treatment> treatArray;
//user inputs all the values (i've cut it down)
Animal* c1 = new Cattle(id,weight,yy,mm,dd,sex,treatArray,category);
vec_Animal.push_back(c1);
}
void administerDose(int id) //Main Problem
{
vector<Animal*>::iterator ite_Animal = vec_Animal.begin();
for(ite_Animal; ite_Animal != vec_Animal.end(); ++ite_Animal)
cout<<"\nVector contains:"<< (*ite_Animal)->calcDose();
}
I'm sorry for the long and messed up question. Final question is, Cattle has extra data member which is category
but the system doesn't recognise this as well. It recognises as if it is Animal
object. Can I have a piece of advice please?
Cheers
every time I try to use
calcDose()
, it automatically calls function inAnimal
class
Sounds like you forgot to make calcDose
a virtual
member function.
Final question is,
Cattle
has extra data member which is category but the system doesn't recognise this as well. It recognises as if it isAnimal
object.
I'm not sure what you mean by the "system" "recognizing" anything, but if you access a Cattle
object through an Animal*
, then you can't get to the Cattle
-specific members. You'd have use either a Cattle*
or, again, polymorphism/virtual
.
Unlike Java (and many other languages), C++ uses what is called "static binding" by default. Static binding means the function called is based on the declared type of the object (or pointer) at compile time, rather than what the object actually is (or what the pointer is actually pointing to).
The alternative to static binding is "dynamic binding". In dynamic binding, the function called is based on what the object actually is (or what the pointer is actually pointing to) at runtime.
To enable dynamic binding, which is what you'll want if you have an inheritance hierarchy set up and are maintaining base class pointers (Animal*s), you have to use the keyword virtual
. virtual
makes a function dynamically bound, so that calls to that function will reflect the actual runtime type of the object (Cattle) rather than the compile time declared pointer type (Animal*).
To declare a function virtual, you put the virtual keyword before the return value on the function declaration (in the class declaration / .h file):
class Animal
{
virtual void calcDose();
// ...
};
It is also good style to put virtual on the overridden function in the derived class (calcDose() in Cattle), although the virtual is implied for inherited functions, so putting it there is not strictly necessary.
The one last thing to make sure you to get dynamic binding, is to make sure you always have pointers (or references) to objects rather than objects on the stack (when you want dynamic binding). An object on the stack (i.e. Animal a) can only be it's declared type, it can't point to a derived class type. So the vector<Animal*>
you have is perfect, because those pointers can point to Cattle objects (or Animal objects), while a vector could only hold actual animal objects.
You should make your calcDose function virtual and redefine it in each subclass: Cattle, etc. Also to recognize your Animal as a Cattle you have to cast it to Cattle class. But you are supposed to use the common base type interface most of the time.
精彩评论