This is one of those things where i just know im doing it wrong. My assignment is simple.
Create 3 classes in c++,
product ,software ,book. product is super, book and software are product.
then make an array of pointers and fill the array with software and books.
so i've done the following
int main()
{
Product *productList[10];
Book *pBook;
Book q(5);
pBook = &q;
pBook->getPrice();
Software *pSoftware;
Software g(5);
pSoftware = &g;
pSoftware ->getPrice();
productList[0] = pSoftware; // fill it with software, cannot do this.
Is there any way of inserting a subclass into a super classes array. Or should i define the array of pointers as something else.
class definitions below
class Product
{
public:
double price;
double getPrice();
Product::Product(double price){};
};
class Book: public Product
{
public:
Book::Book(double price)
:Product(price)
{
}
double getPrice();
};
class Software: public Product
{
public:
Software::Software(double price)
:Product(price) // equivalent of super in java?
{
} // code of constructor goes here.
double getPrice();
};
You should use public inheritance:
class Book : public Product {
...
};
[edit]
You should also declare getPrice() as virtual if you want to implement it differently in the child classes. This will make compiler call getPrice() of the right child class when you call getPrice() for a pointer to a Product:
virtual double getPrice();
As the array is of type Product, you should declare pSoftware as a pointer to Product:
Product *pSoftware = new Software(5);
// ...
productList[0] = pSoftware;
It's been a while, but what's the default inheritance type in C++? Should
class Book:Product
{
be
class Book: public Product
{
It's always a good idea to be explicit anyway.
Can't you just cast the software* to a product* to put it in your array?
productList[0] = (Product*)pSoftware;
Related
I'm new to C++ and could really appreciate some help. I have a Base class and several class types derived from this. I'm trying to use polymorphism to add these derived objects to a vector of type Base class. After spending some time looking into this, it seems as though the recommended way to do this is using pointers. However, when I try and implement this I get an error message (in intellisense) stating that there is no known conversion between the base and derived class types.
I've included some example code for what I'm trying to achieve. Apologies for such a silly / trivial example, but I'm not allowed to show any of the actual code I'm working on. In this example, in the header file I have an abstract base class "Meal", and two types of derived classes : "SingleCourseMeal" and "ThreeCourseMeal". In the "Restaurant" class I have a vector of type unique_ptr<Meal>
In the cpp file I read from file and create a unique_ptr of either a SingleCourseMeal or a ThreeCourseMeal type, depending on the information in the file. I assign the relevant variables to the dereferenced pointer (from information in the file), and finally add the unique_ptr to the unique_ptr vector in the Restaurant object. However, I'm unable to add a pointer to a ThreeCourseMeal or a SingleCourseMeal to the unique_ptr<Meal> vector.
Could anyone advise where I'm going wrong, and/or how best to implement polymorphism like this? (i.e. populating a vector of type Base with Derived objects)
header file:
class Meal
{
public:
String cuisineType;
double prepTime;
virtual void setRecipe() = 0;
};
class MultipleCourseMeal : public Meal
{
public:
Vector<String> courses;
double intervalBetweenCourses;
void setRecipe() override {}
};
class SingleCourseMeal : public Meal
{
void setRecipe() override {}
};
class Restaurant
{
Vector<std::unique_ptr<Meal>> meals;
};
cpp file:
String cuisineType = getCusineTypeFromFile();
double prepTime = getPrepTimeFromFile();
if (numberOfCourses > 1) {
std::unique_ptr<MultipleCourseMeal> meal = std::make_unique<MultipleCourseMeal>();
Vector<String> courses = getCoursesFromfile();
double intervalBetweenCourses = getIntervalFromFile();
meal->cuisineType = cuisineType;
meal->prepTime = prepTime;
meal->courses = courses;
meal->intervalBetweenCourses = intervalBetweenCourses;
Restaurant.meals.push_back(meal);
}
else {
std::unique_ptr<SingleCourseMeal> meal = std::make_unique<SingleCourseMeal>();
meal.cuisineType = cuisineType;
meal.prepTime = prepTime;
Restaurant.meals.push_back(meal); //THIS IS WHERE THINGS GO WRONG
}
I have a base class
class Servicii{
protected:
double price;
public:
Servicii(double p):price(p){}
double getPrice(){return price;}
and 3 derived classes Car Book House.Because they are derived class,all of them will have a price
class House:public Servicii{
private:
int level;
public:
House(double p,int l):
Servicii(price),level(l){}
And in main I create some objects like this:
House *h1=new House(600,3);
Book *b1=new Book("Dostoievski","Crima si Pedeapsa",5,98.5);
My problem is that when i print the price is always 0 .For example the house has the price 600,but when i printed it it is 0 and i don't know why.
I've made a print function in Servicii and all dervied classes inherits this function+ they print their own attributes.
In this constructor:
House(double p,int l):
Servicii(price),level(l){}
you are using the base class member price to initialize Servicii. This is incorrect, and it is in fact undefined behavior to access this member before the base class has been initialized completely.
You just need to use the value p to initialize Servicii instead:
House(double p,int l):
Servicii(p),level(l){}
If you turn on compiler warnings, you will be warned about making these kinds of mistakes.
This question already has answers here:
Can a c++ class include itself as an member?
(4 answers)
Closed 4 years ago.
I'm fairly new to c++ with most of my writing having been in Python.
In Python, if I wanted to create a class to hold information about a Human, I could write a class which could hold its 'parent' as one of its variables. In Python, I'd do it roughly like this:
class Human:
def __init__(self, name):
self.name = name
first = Human("first")
second = Human("second")
second.parent = first
where second.parent = first is saying that the parent of the Human second is the Human first.
In c++ I tried to implement something similar:
class Human {
public:
Human parent;
};
int main() {
Human first = Human();
Human second = Human();
second.parent = first;
}
This example comes with an error that field has incomplete type: Human. I get this, because it's saying that I can't have a Human in my Human object because there isn't yet a full definition of what a Human is. When I search for related posts, I keep coming up against solutions using forward declaration and pointers but I haven't been able to make it work properly.
I'd really appreciate any help in making the c++ example behave how I want it to.
Thanks.
For example by using pointers:
struct Human
{
Human* parent; // The symbol Human is declared, it's okay to use pointers to incomplete structures
};
int main()
{
Human first = Human();
Human second = Human();
second.parent = &first; // The & operator is the address-of operator, &first returns a pointer to first
}
You can use references as well but those could be a little harder to work with and initialize.
Pointers make sense here, Pointers hold the memory address to whatever you are referencing without storing the actual data within that class.
E.G
class Human {
public:
Human * parent;
};
Your parent is now actually stored as a memory address but with *parent it is being used an object, e.g you could do:
myHuman.parent->parent (-> meaning de-reference and then ".")
What you can do is
class Human {
public:
Human * parent = nullptr;
};
It should be a pointer, & better initialized.
You can do it by keeping a pointer property in the class of the same type.
Like
class Human {
...
...
public : Human* parent;
...
...
}
And can be used as:
int main()
{
Human* h1 = new Human;
Human* h2 = new Human;
h2->parent = h1;
...
...
delete h1;
delete h2;
}
I am working on a game project, and my teammate has a certain way of solving our reference issues, and it works great, except, when the game is big, we will end up with massive constructors.
class Player
{
private:
Weapon *w1, *w2, *w3;
Armor *a1, *a2;
public:
Player(Weapon *w1, Weapon *w2, ...) : w1(w1), w2(w2), ...;
}
Then my constructor is Player(w1, w2, w3, ...); which is disturbing, what if the player class had 100 references?
Is there a way to make this syntax simpler, or are we doing it wrong? Is there a better way of making references to variables which are outside the player class?
IMPORTANT
The above is purely an example, a poorly written one. I don't just have weapons and armors. I have a ton of classes. I have a developer console reference, I have armor references, items, I have references to the debugging class, the logger class, and the list goes on. A vector is not helpful for me. Sorry for the poor example.
Why not use vectors ?
std::vector<Weapon *> W;
std::vector<Armor *> A;
You can indeed put it all in a single vector, if you use inheritance.
For a fantasy-themed game (which I assume you're writing) it could be something like this:
// The base object, contains common attributes
class Object { ... };
// The item class
class Item : public Object { ... };
class Weapon : public Item { ... };
class Sword : public Weapon { ... };
class Clothing : public Item { ... }
class Armour : public Clothing { ... };
Then it's enough with one vector for all equipment:
std::vector<std::shared_ptr<Item>> inventory;
For worn stuff, you could have separate variables, like
std::shared_ptr<Weapon> wielded;
std::shared_ptr<Clothing> head; // Helmets, hats, etc.
Or use a map for the equipped stuff:
std::unordered_map<std::string, std::shared_ptr<Item>> equipped;
Then you can use e.g.
equipped["wielded"]
to get the wielded item.
For completeness, some other possible classes in the class tree above might be:
class Character : public Object { ... }
class Player : public Character { ... }
class Monster : public Character { ... }
class Dragon : public Monster { ... }
class RedDragon : public Dragon { ... }
class TheUltimateBossDragon : public RedDragon { ... }
As a side note, I have used hierarchies like the above in my own games previously. However in my next game (when and if I get that far) I will probably use another pattern, where classes indicates behavior. For example, a sword is equipable, it's a damage_inflicter, it's takeable, etc. This means more complex inheritance hierarchies, with much more multiple inheritance, and will probably use RTTI more. But on the bright side it will hopefully be more flexible.
Rather than having a fixed number of pointers to a small number of types, try using vectors:
class Player
{
private:
std::vector<Weapon*> weapons;
std::vector<Armor*> armors;
public:
Player(const std::vector<Weapon*>&, const std::vector<Armor*>&);
}
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
C++ How to create subclass in class with array
Hi guys, i still learning C++ and face some issues here.
Basically i got a parent class
lets call this parent class as
Vehicle
It got 2 sub class, lets assume they are
Car and Motorcycle
I will create a vehicle object assume vehicle size is 20
Vehicle veh[20]
I will do the following
string vType;
cout << "Please enter your vehicle Type:";
cin >> vType;
so i do a comparision if (vType=="Car")
it will return 4 wheels from the sub class, but how do i declare its 4 wheels at Car and 2 wheels at Motorcycle , i know i need create 2 additional cpp file which is
class Car : public Vehicle
{
private:
int noOfWheels;
public:
computePrice();
}
But how do i set noOfWheels specially to Car as 4 and Motorcycle as 2.
The next is the tricky part.. after knowing how many wheel it is
i will need store a array for each wheel
string wheel[4];
since i know there 4 wheel in cars.
How do i prompt 4 type and store it in an array, and all of this in an object call Vehicle.
I can use a for loop and thats not the issue, the part i am stuck on is how do i create a string array and store the 4 prompt and then into this Vehicle[0]
wheel 1:
wheel 2:
wheel 3:
wheel 4:
When user want to print data it will be
Vehicle[0]
Type: Car
Wheel: 4
Wheel[0] = Fine condition
Wheel[1] = Need to check again
Wheel[2] = Fine condition
Wheel[3] = Might need get repair
Thanks for all help.
Firstly the declaration for your array is wrong. Since you are dealing with polymorphic classes you need to use pointers.
Vehicle* veh[20];
Otherwise you will have what is called object slicing. Which means that even if you create a Car or a Motorcycle they will be converted into Vehicles when you assign them to your array.
'how do i set noOfWheels specially to Car as 4 and Motorcycle as 2.'
In the constructor
class Car : public Vehicle
{
public:
Car() : noOfWheels(4) { ... }
private:
int noOfWheels;
...
};
class Motorcycle : public Vehicle
{
public:
Motorcycle() : noOfWheels(2) { ... }
private:
int noOfWheels;
...
};
But personally I don't think you need a noOfWheels data member at all. Since the number of wheels is fixed for each type of Vehicle it's a waste of space, instead you need a virtual function
class Vehicle
{
public:
virtual int noOfWheels() const = 0;
...
};
class Car : public Vehicle
{
public:
virtual int noOfWheels() const { return 4; }
...
};
class Motorcycle : public Vehicle
{
public:
virtual int noOfWheels() const { return 2; }
...
};
'how do i create a string array and store the 4 prompt and then into this Vehicle[0]'
Again I would use the constructor to initialize the car wheel names.
class Car : public Vehicle
{
public:
Car(const std::string* w)
{ wheel[0] = w[0]; wheel[1] = w[1]; wheel[2] = w[2]; wheel[3] = w[3]; }
virtual int noOfWheels() const { return 4; }
private:
std::string wheel[4];
...
};
Use constructors to initialize classes. That's what they are for.
Looks like the answer has been accepted, but I typed it all so I will post it all. It's a run down of OOP I guess.
Lets assume that all vehicles have wheels. All those wheels have a condition. Some vehicle have more or less wheels than others.
You need to separate the common aspects of the classes into higher orders, into base classes.
You also need to organize your classes to compose themselves with other classes to build a whole.
Here we have a wheel class, it has a condition, which is a string. You can query it's condition at any time.
class Wheel
{
public:
const std::string GetCondition() const { return mCondition; }
private:
std::string mCondition;
};
We know that a vehicle is going to have wheels, so we store the wheels container here, to share out among the child classes through inheritance.
class Vehicle
{
public:
Vehicle(unsigned int wheelCount) { mWheels.resize(wheelCount, Wheel()); }
virtual unsigned int GetWheelCount() { return mWheels.size(); }
virtual const std::string GetWheelCondition(int wheelNumber)
{
return mWheels[wheelNumber].GetCondition();
}
protected:
std::vector<Wheel> mWheels; // All vehicles have wheels.
};
A car is a type of Vehicle. Therefore it inherits from Vehicle. It has inherited a member that holds Wheel objects. It has also inherited methods that help to find the wheel count and to get the status of a wheel by index. This is the level that you can specialize you classes. The Car and Motorbike class both have wheels, and they have the same core functionality. We can specialize the class by adding or overloading a method.
class Car : public Vehicle
{
public:
Car() Vehicle(4) {}
Car(unsigned int wheelCount) : Vehicle(wheelCount) {}
}
class Motorbike : public Vehicle
{
public:
MotorBike(unsigned int wheelCount) : Vehicle(wheelCount) {}
void DoWheelie() { throw; }
}
We can use these object like so,
Car car(4); // Car with 4 wheels. specialized constructor.
Car standardCar(); // Car with 4 wheels, as default constructor.
Car uberCar(42); // Car with 42 wheels.
Motorbike bike(2); // Bike with 2 wheels.
Motorbike badBike(); // No default constructor defined! Will not compile!
car.GetWheelCount(); // 4
bike.GetWheelCount(); // 2
bike.DoWheelie(); // All good.
car.DoWheelie(); // NOPE! Method doesn't exist for this.
There is more to say on the benefits of polymorphism and heap allocation, but I think I'll leave it here. Hope it's helpful.