I have simple problem:
class Weapon{
public:
int dmg;
float speed;
int rate;
};
class Uzi : public Weapon{
public:
Uzi();
void Shot(float angle);
};
Class Pistol : public Weapon{
public:
Pistol();
void Shot(float angle);
};
Later in code when I reserve for example:
Weapon wep;
wep = Uzi;
wep.Shot(15);
It doesn't work:
undefined reference to `Weapon::Shot(float)'
Can I reserve different type of 'wep' variable?
I think no because weapons are changing(pistol/uzi/...).
Thanks in advance!
Weapon wep;
wep = Uzi;
This is slicing. Uzi is-a Weapon, but not the other way around. You can use pointers for this:
Weapon* wep = new Uzi();
Also, you get the error because there is no Shot() method in the Weapon() class.
You might want to declare it virtual and also make it abstract (optional). You make it virtual to allow polymorphism.
That way:
Weapon* wep = new Uzi();
wep->Shot();
will call Shot() in the Uzi class, although it's called on a Weapon pointer.
The following should work:
class Weapon{
public:
int dmg;
float speed;
int rate;
virtual void Shot(float angle) {}; //move implementation to cpp file
};
You forgot to declare void Shot(float angle) in the Weapon class.
For polymorphism, you need to virtualise the method, Weapon should declare:
virtual void Shot(float angle) = 0;
and then each subclass should implement the virtual method.
Edit: Oh, and you can't just assign constructors to one another, you need to instantiate a concrete subclass, i.e:
Weapon *weapon = new Uzi();
as mentioned in several other answers.
Related
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.
I've been having trouble accessing the "getDegreeProgram()" method in my objects that are set to my array of pointers; all of my baseclass methods are working, but for some reason, my subclass methods aren't even visible. I'm suspecting that I don't have the syntax right, and its converting all of my subclass objects to the baseclass of student.
roster.h:
class roster {
private:
student** classRosterArray; //array of pointers
roster.cpp function that creates my objects and sets them to the array of pointers
void roster::createStudentObject() {
classRosterArray = new student *[5]; //array of pointers
if (degreeProgramInput == "NETWORK") {
classRosterArray[rosterCounter] = new networkStudent();
}
else if (degreeProgramInput == "SECURITY") {
classRosterArray[rosterCounter] = new securityStudent();
}
else classRosterArray[rosterCounter] = new softwareStudent();
}
student.h subclasses in question (they're subclasses of my baseclass "student")
class networkStudent:public student {
private:
int networkDegree;
public:
int getDegreeProgram();
networkStudent();
};
class securityStudent:public student {
private:
int securityDegree;
public:
int getDegreeProgram();
securityStudent();
};
class softwareStudent:public student {
private:
int softwareDegree;
public:
int getDegreeProgram();
softwareStudent();
};
As far as I understood, you are trying to access the elements of classRosterArray and trying to call getDegreeProgram().
For this problem, Make the getDegreeProgram() virtual function.
student.h
class student {
...
public:
virtual int getDegreeProgram() = 0; // pure virtual function
};
Subclasses of student
class networkStudent:public student {
private:
int networkDegree;
public:
virtual int getDegreeProgram();
networkStudent();
};
class securityStudent:public student {
private:
int securityDegree;
public:
virtual int getDegreeProgram();
securityStudent();
};
class softwareStudent:public student {
private:
int softwareDegree;
public:
virtual int getDegreeProgram();
softwareStudent();
};
Suggestion:
In this case, Because getDegreeProgram() seems to be a getter function, I think you should declare it as a const function.
Edit:
As rightly said by Richard, In C++ 11, override keyword was introduced for this purpose for the sub classes. So, instead of writing virtual int getDegreeProgram();, you could write int getDegreeProgram() override; also.
There are two you ways you can go about it.
Runtime Polymorphism - This method will require less code refactoring but at the cost of runtime. Each instance of a polymorphic class will have a pointer(vptr) to a table(vtable) of pointers to the different versions of the virtual function. This table will be used for finding the right version of the virtual function at runtime.
You can achieve runtime polymorphism here by making the getDegreeProgram function virtual in base class ie., Student and override it in derived classes ie., securityStudent, networkStudent and softwareStudent.
class Student {
...
public:
virtual int getDegreeProgram() = 0; // notice the virtual keyword and 0 at the end.
// 0 is for saying that it is pure virtual, meaning
// we don't have any definition for this function in
// this class. Such a class is also called as
// abstract class
...
}
class securityStudent : Student {
...
public:
int getDegreeProgram() override
{
// do the stuff you want to do
}
...
}
// driver stub
...
Student *student;
securityStudent sStudent;
networkStudent nStudent;
.
.
student = &sStudent;
student->getDegreeProgram(); // calls security student implementation of getDegreeProgram
student = &nStudent;
student->getDegreeProgram(); // calls network student implementation of getDegreeProgram
...
Static Polymorphism or CRTP or Simulated Dynamic Binding - This method does the same thing as above but with the advantage of knowing the type at compile time by means of some casting magic (below). Even this approach has its limitation like kludgy syntax and some amount of refactoring which is a lot more than in the 1st case and lack of readability due to terseness of templates etc.
The trick here is to get the derived class' information at compile time and typecast the this pointer of the base class to that of the derived class. :-)
template <typename StudentType>
class Student {
...
public:
int getDegreeProgram()
{
return (static_cast<StudentType*>(this))->getDegreeProgramImpl();
}
...
}
class securityStudent : public Student<securityStudent> {
...
public:
int getDegreeProgramImpl()
{
// write your specifc implementation here
}
...
}
// driver stub
...
securityStudent sStudent;
networkStudent nStudent;
.
.
sStudent.getDegreeProgram(); // calls security student implementation of getDegreeProgram
nStudent.getDegreeProgram(); // calls network student implementation of getDegreeProgram
...
I'm wondering about the available alternatives to run-time polymorphism, specifically, an alternative to having a common base class between my classes in order to store and interact with instances of derived classes.
RTP has disadvantages of indirection through vtable look-up, and also forces the derived classes to be stored as pointers, and so generally they must be dynamically allocated. From what I've been told, this hinders inlining and compiler optimisations.
In short, I don't want this:
class Animal
{
public:
virtual void noise() const = 0;
};
class Dog : public Animal
{
public:
virtual void noise() override const {std::cout<<"Woof!\n";};
};
class Cat : public Animal
{
public:
virtual void noise() override const {std::cout<<"Meow!\n";};
};
//...
std::vector<Animal*> animals;
I want something like this:
class Dog
{
public:
void noise() const {std::cout<<"Woof!\n";};
};
class Cat
{
public:
void noise() const {std::cout<<"Meow!\n";};
};
//...
std::vector<*Things that have noise()*> animals;
In your example, I can not help you, but for classes with data members, here is an optimization.
Let's suppose we want to create a bullet-hell game.
In a naive approach, we need a class Bullet :
class Bullet {
public:
void draw(Renderer& r);
virtual void update_logic(float delta);
void run_physics();
protected:
float vx, vy; //velocity
private:
float x, y; //position
//...
};
So, the update_logic method would be called to set the velocity of the bullet, then run_physics will apply this velocity to the position.
Modifying logic needs polymorphism, so your collection becomes std::vector<Bullet*> (or std::vector<std::unique_ptr<Bullet> > in modern c++).
Then, in your main loop, first you update the logic, then the physics, then you draw your bullets.
Of course it is inefficient because of pointer dereference and vtables etc.
What you can do instead is :
class Bullet {
public:
void draw(Renderer& r);
void update_logic(float delta) { logic->update(delta); };
void run_physics();
void setVelocity(float, float);
void setLogic(BulletLogic*);
private:
float x, y, vx, vy;
BulletLogic* logic;
};
So now, you can use std::vector<Bullet>, and the indirection will occure only when updating logic, but neither while running phyics or drawing the bullet.
I'd welcome some help with C++ inheritance to get a better grasp of the concept.
Is it possible to "extend" member types when creating a derived class? I think my problem can be best demonstrated by a simple example, where I'd like to extend the class VehicleData with a new double variable:
class VehicleData {
int yearOfManufacture;
//Different routines, for example Serialize(), etc., warranting to create a class for just a bunch of variables
};
class BicycleData:VehicleData {
double frameHeight; //new property that only applies to bicycles
};
//Now I create the actual classes that use the types above
class Vehicle {
VehicleData data;
void PrintData(); //a function that works on basic vehicle data
};
class Bicycle:Vehicle {
BicycleData data; //should copy VehicleData when creating an instance of this class
};
The problem with this approach is that when I code the above and create a Bicycle instance, its BicycleData member hides the already existing VehicleData member.
Is there a way to extend the base class, i.e. simply add a new double variable (to store frame height in this example), and keep the already existing (year of manufacture) data?
As far as I can tell, there is no clean way to do exactly what you want with inheritance alone.
You could create a template out of your base class:
template <typename Data>
class BaseVehicle
{
Data data;
// etc.
};
class Vehicle : BaseVehicle<VehicleData>
{
// etc.
};
class Bicycle : BaseVehicle<BicycleData>
{
// etc.
};
Then the Vehicle and Bicycle classes would contain data field of VehicleData and BicycleData types respectively.
Since in your example Bicycle inherits from Vehicle privately (i.e. there is no support for using Bicycle polymorphically via pointer/reference to Vehicle), this would effectively be identical to what you want to achieve.
If you do want dynamic polymorphism, you should create a separate, preferably abstract, class, defining the interface for your vehicles, e.g.:
class VehicleInterface
{
public:
// Some pure virtual interface methods
virtual void moveTo(const Vector2 position) = 0;
virtual ~VehicleInterface() = default;
};
And then you can have your concrete vehicles inherit and implement this interface:
class Vehicle : BaseVehicle<VehicleData>, public VehicleInterface
{
public:
virtual void moveTo(const Vector2 position) override
{
// implementation for Vehicle
}
};
class Bicycle : BaseVehicle<BicycleData>, public VehicleInterface
{
public:
virtual void moveTo(const Vector2 position) override
{
// implementation for Bicycle
}
};
Then any function, which would like to work with vehicles polymorphically, can just accept a reference or a pointer to VehicleInterface:
void driveToWork(VehicleInterface* vehicle)
{
vehicle->moveTo(getWorkPosition());
// etc.
}
Short answer; Not in the way that you're aiming for, but you can achieve something similar.
Rather than have an instance declared as you have, if you make data a pointer. You can then have BicycleData inherit VehicleData and then just replace data with the new instance in the constructor of the Bicycle.
ie
class Vehicle {
void PrintData();
protected:
void replaceData(std::shared_ptr<VehicleData> d) {
data = d;
}
std::shared_ptr<VehicleData> getData() {
return data;
}
template<class T>
std::shared_ptr<T> getDataAs() {
return std::dynamic_pointer_cast<T>(data);
}
private:
std::shared_ptr<VehicleData> data;
};
class Bicycle:Vehicle {
Bicycle(){replaceData(std::make_shared<BicycleData>());}
std::shared_ptr<BicycleData> getData() {
return getDataAs<BicycleData>();
}
};
I need a way for a single variable to represent two kinds of objects derived from the same base class.
It's kinda hard to describe but I'll try the best:
Say the base class:
class Rectangle
{
float w;
float h;
const float area() {return w*h;}
};
And the two derived classes:
class Poker : Rectangle
{
int style; // Diamond, Club, ....
int point; // A~10, J, Q, K
};
class BusinessCard : Rectangle
{
string name;
string address;
string phone;
};
Now is it possible to declare an object, which could be either a poker or a business-card?
'cuz the usage below is illegal:
Rectangle* rec;
rec = new Poker();
delete rec;
rec = new BusinessCard();
Polymorphism might be a way but since it's only good for changing base-class' member attributes, I need this object to be able to represent exactly either of the derived objects.
EDIT:
Thanks for the all the answers. The public inheritance , the virtual destructor and even the boost::variant typedef are all fantastic hints.
You can do that. The problem is the inheritance modifier for classes is private. Most of the time, private inheritance is not what you want to use. Instead, declare it explicitly as public:
class Rectangle
{
float w;
float h;
const float area() {return w*h; }; // you missed a semicolon here, btw
virtual ~Rectangle() { } // to make `delete` work correctly
};
class Poker : public Rectangle // note the public keyword
{
int style; // Diamond, Club, ....
int point; // A~10, J, Q, K
};
class BusinessCard : public Rectangle
{
string name;
string address;
string phone;
};
Then your code snippet should work.
You need to change the qualifier for the inheritence to public.
class Poker : public Rectangle
{
int style; // Diamond, Club, ....
int point; // A~10, J, Q, K
};
class BusinessCard : public Rectangle
{
string name;
string address;
string phone;
};
is what you want. Now both classes, BusinessCard and Poker are of type Rectangle.
I need this object to be able to
represent exactly either of the
derived objects.
Don't know if I understand it correct but have a look at boost::variant
typedef boost::variant<Poker, BusinessCard> PokerOrBusinessCard
Now you can access the derived classes with a boost variant visitor class.
Maybe this can be a solution.
I think what you may be looking for is multiple inheritance, where an object can sometimes be a Poker and sometimes a BusinessCard.
See here for a tutorial:
http://www.deitel.com/articles/cplusplus_tutorials/20060225/MultipleInheritance/index.html
Note that you can decide to make it one or the other if you wish, it does not have to be both all of the time, which may satisfy what you need.
Change the subclasses to use public derivation and your code works, with some cleanup. You should also use virtual destructors so the delete works correctly.
class Rectangle
{
float w;
float h;
const float area()
{
return w*h;
}
public:
virtual ~Rectangle(){};
};
class Poker : public Rectangle
{
int style; // Diamond, Club, .... int point; // A~10, J, Q, K
};
class BusinessCard : public Rectangle
{
string name;
string address;
string phone;
};