C++ How to create subclass in class with array [closed] - c++

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.

Related

Dynamically creating two objects and assigning one to the other [duplicate]

The goal of my program is to allow the user to enter up to 100 names for people and 100 names for cars. Then the user can "register" a car to as many people as s/he wishes using pointers. I know I need a person class and a car class and I need to use two arrays of size 100 for each. But I am completely lost on how to set anything else up. I have done a lot of researching to try and figure something out. I would be extremely appreciative if anyone could give me some basic example code for how something like this could be done.
I don't have much code:
class Person{
public:
person();
Car* in_car;
};
class Car{
public:
Car();
};
int main()
{
Car cars[101];
Person people[101];
}
You could add a vector of car pointers to the People class.
class People{
...
private:
vector<Car*> _pointer;
};

Inheritance and lists

I need to manage ants and colonies for a little game (for experiments in fact).
I have an Element class, which define all the entities in the game (ants, colonies, food, and other stuff…)
All other classes derive from this one.
My problem :
I have a class to manage all the entities. The player is able to select what he want. The selected entity is stored : Element* selection; If the selected intity is an Ant, the player can move it. But, because the selection variable is an Element pointer, I can't call the move() method which is in the Ant class, obviously.
What I consider to test :
If I implement a Element method called isMovable() which return true or false and maybe if the selection is movable, I will cast it to an Ant ? I don't know what is the right solution.
My move method:
void Manager::movementEvent(sf::Vector2i mPosition)
{
sf::Vector2f mousePosition = sf::Vector2f((float)mPosition.x, (float)mPosition.y);
if(this->selection) {
// I need to move the selected Ant
}
}
Thank you for your help !!
EDIT
Here my actual design :
class Element {
private:
sf::Vector2f position;
int width, height;
public:
Element();
Element(sf::Vector2f position, int width, int height);
Element(const Element & element);
virtual ~Element();
};
class Colony: public Element {
private:
int capacity;
Queen *queen;
public:
Colony();
Colony(sf::Vector2f position, int width, int height, int capacity, Queen &queen);
Colony(Colony const & colony);
virtual ~Colony();
Colony& operator=(Colony const& colony);
};
class Ant: public Element
{
private:
sf::Vector2f destination;
int number, age, speed;
public:
Ant();
Ant(sf::Vector2f position, int number, int age, int width, int height, int speed);
Ant(const Ant & ant);
virtual ~Ant();
Ant& operator=(Ant const& ant);
};
class Manager {
private:
std::vector<Element*> ants;
std::vector<Element*> colonies;
Element* selection;
std::vector<Ant*> movement;
public:
Manager();
virtual ~Manager();
std::vector<Element*> getAnts();
std::vector<Element*> getColonies();
void addAnt(Ant* ant);
void addColony(Colony* colony);
void removeAnt(Ant* ant);
void removeColony(Colony* colony);
void draw(sf::RenderWindow * window);
void drawElement(sf::RenderWindow * window, std::vector<Element*> vector);
void selectionEvent(sf::Vector2i mousePosition);
bool checkSelection(sf::Vector2f mousePosition, std::vector<Element*> vector);
void movementEvent(sf::Vector2i mousePosition);
};
I would prefer to avoid the design in general, as it strikes me as a forced fit at best.
A base class should define behaviors that are common between a number of derived classes and provide a common interface to that common behavior. In this case, however, it seems likely to me that your derived classes have practically no common behavior, so you'll have little or nothing in the way of a useful common interface between them.
That being the case, you're likely to lose a great deal more than you gain by forcing them all to derive from a (basically meaningless) "entity" class. In fact, I'd suggest that almost any time you find yourself thinking in terms of a class name as general as "object" or "entity" that doesn't suggest a meaningful set of behaviors, chances are pretty good that you're trying to shove things together that don't really belong together.
All that said, if you really insist on doing this anyway, I'd adhere to the basic maxim that it's better to tell than ask. As such, I'd define a try_to_move (or possibly just name it move) in the base class, but provide a default definition that just fails. Then override that in the Ant class to actually move.
class Entity {
// ...
virtual bool move_to(Location new_location) {
return false;
}
};
class Ant : public Entity {
// ...
virtual bool move_to(Location new_location) {
my_location = new_location;
return true;
}
};
This way you can tell anything derived from Entity to move -- but if you tell a Food object to move, it'll just fail. This simplifies the calling code considerably. Instead of a pattern like:
if (object->can_move()) {
if (object->move_to(new_location))
// succeeded
else
// failed
}
We get code like:
if (object->move_to(new_location))
// succeeded
else
// failed
At least in a typical case, we're likely to end up dealing with the possibility of failure even when we've told an ant to move, so adding the element of asking the object whether it can move before asking it to do so really gains us nothing anyway.
Depending on the situation, you might want to change the code a little, so different reasons for failing to move return different error codes, so when/if it fails, you can sort out why. Alternatively, you might prefer to write the code so that it either succeeds at moving, or else throws. Under these circumstances (where you rather expect it to fail at least part of the time) that's probably not the best alternative, but it may still be worth considering.
I'll reiterate, however, that I think a better design is probably to just keep Ants and Food separate, so it's easy to deal with Food as food, and Ants as ants, and not have to sort out at run-time whether something is Food or an Ant to know how you can interact with it.
This really smells like you are solving the wrong problem. You will be able to get it to work using flags like isMovable and casting, but your code is likely to turn into a mess and give you a headache.
Perhaps your problem is actually
"I have a class to manage all the entities"
If they are in no way related, they probably should not express an Is-A relationship to Entity. It might be cleaner if you have different containers for each type. How you tie up the actions the user wants with "entities" will be another matter.
You can add a virtual method move() on your base class, than implement it only for the Ant class, so when it's checked the Element is movable, it should move:
class Element
{
public:
Element(bool movable) : m_movable(movable) {}
virtual void move() {};
bool isMovable() const { return m_movable; }
private:
bool m_movable;
};
class Ant : public Element
{
public:
Ant() : Element(true) {}
void move() { /* move */ }
};
class Food : public Element
{
public:
Food() : Element(false) {}
};
In this way every derived class has a move() method, indeed, but it's the inherited from the base class (so it's left blank).
EDIT
Occam's razor tells us that in this case you also don't have the need of the bool m_movable flag, so the snippet simplifies in:
class Element
{
public:
Element() {}
virtual void move() {};
};
class Ant : public Element
{
public:
Ant() {}
void move() { /* move */ }
};
class Food : public Element
{
public:
Food() {}
};

Initializing references in the constructor

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*>&);
}

C++ counting animals and random interaction with base class

My assignment is
"My dog, named Buddy, lives in the backyard. He barks at night when he sees a cat or a squirrel that has come to visit. If he sees a frog, and he is hungry, he eats it. If he sees a frog and he isn't hungry, he plays with it. If he has eaten 2 frogs already, and is still hungry, he will let it go. If he sees a coyote, he crys for help. Sometime his friend Spot stops by, and they chase each other. If he sees any other animal, he simply watches it.
Write one test program and a set of classes that keeps track of all of the backyard activity and stores the results into a file for a given night. I would expect that you would have an animal class, and a cat, dog, squirrel, coyote class that inherits from the animal class. You would need to keep track of how many frogs he has eaten, how many animals of each type has come and visited, how often he has played and other such details. "
You will also need to write a test program that will read the file that was generated from the other test program, and print out how many animals of each type that he has seen, what he has done with them on a particular day. The user will need to enter in the date, and the information from the file for that date will be read in, and displayed.
Add in any other capability to the program that you need so it covers all of the required programming concepts listed. Be creative with this assignment.
-We are to use classes, data abstraction, inheritance, composition, pointers, operator overloading, and exception handling.-
#include <iostream>
#include <cstdlib>
using namespace std;
class animal{
public:
animal();
~animal();
void interactWithBuddy();
virtual int ID()
{
return ID;
}
};
class frog: public animal
{
public:
void interactWithBuddy();
void eat();
void play();
void letGo();
};
class dog: public animal
{
public:
void interactWithBuddy();
void chase();
};
class cat: public animal
{
public:
void interactWithBuddy();
void bark();
};
class coyote: public animal
{
public:
void interactWithBuddy();
void cryForHelp();
};
class squirrel: public animal
{
public:
void interactWithBuddy();
void bark();
};
class otherAnimal: public animal
{
public:
void interactWithBuddy();
void watch();
};
int main ()
{
srand(time(0));
int number;
std::cout << (rand() % 6 + 1) <<std::endl;
animal * a = new frog();
int z = a->ID();
animal * b = new dog();
int y = a->ID();
animal * c = new cat();
int x = a->ID();
animal * d = new coyote();
int w = a->ID();
animal * e = new squirrel();
int v = a->ID();
animal * f = new otherAnimal();
int u = a->ID();
return 0;
}
I know the code is just a shell but am I on the right track? How would you suggest counting the frogs and figuring whether they get eaten, played with, or let go? Also I want to assign each animal subclass a number in which I can then randomize in the main function so as to correlate with the assignment but I am unsure as to how that would be done. Tips and pointers would be greatly welcome.
You are putting too much into the base class. Not all animals can do all the stuff that others can as well. Your animal class should only contain stuff that any animal can have/do. All the stuff that is specific for a concrete animal (i.e. a dog or a frog) should be placed into the corresponding class. For example, not every animal can bark(), definitely, so this function should not be in the base class.
How would you suggest counting the frogs and figuring whether they get eaten, played with, or let go?
Well since its the dog who can see the frogs, it would make sense to put a counter into the dog class.
Also I want to assign each animal subclass a number in which I can
then randomize in the main function so as to correlate with the
assignment but I am unsure as to how that would be done.
I didn't quite understand what do you mean here. Do you mean that you want to make identifiers for each class? If yes, why would you need to do it?
UPD:
Yes that's a right approach. The easiest way is to assign numbers from 1 to 6 for each animal, and then when you need to determine which one appears, generate a random number in the range of [1,6]. To assign numbers to the animals, you should add a field like int id; and assign different values to it in each class.
UDP 2:
This is where polymorphism comes into play. First of all, to initialize a const member for a class, you need to make it static. Here's a simple example:
class base
{
public:
static const int ID = -1;
};
class derived: public base
{
public:
static const int ID = 1;
};
Now every object of the base class will have an ID of -1, and every object of the derived class will have an ID of 1. However, if you try to use it from a base-class-pointer like this:
base * a = new derived();
int t = a->ID;
you will always be getting -1, since the base class pointer doesn't know what is it pointing it.
To get a correct ID you will need to make a virtual function:
virtual int getId(){ return ID; }
Now if you will do
base * a = new derived();
int t = a->getID();
you will always get the right ID from the "real" type a points at.
I suggest you put the random logic outside the tool... separation of concerns. Then you can have one program that just reads a series of animal names from standard input, performs the actions and records whatever it needs, then when it detects end-of-file prints a summary report. You can test it simply as in:
echo cat frog frog squirrel frog | buddy_simulator
If you want, you can then create a program to randomise some input.
The basic logic should be:
std::string animal_name;
while (std::cin >> animal_name)
{
// do something animal_specific
}
// do reporting
The animal specific behaviour could be created using a factory method accepting the animal_name parameter and returning an appropriate Animal* to a newly heap allocated animal object. You could then call p->suffer_buddy();, which would update a static member "times this animal's been seen" counter, print out what buddy likes to do (on this sighting). If it's the first time that animal's been seen, you could store the pointer into a vector in main(), so that when you want to do a summary report, you could call p->report() for each animal type you've encountered. Frog::report(), for example, might be something like:
void Frog::report()
{
std::cout << "of " << count_ << " frogs, " << eaten_ << " eaten, " << played_with_ << " played with, " << let_go_ << " let go\n";
}
It's a bit ugly to use so many static variables, but it's easier to make it work like this.
(Unfortunately, the behaviour's badly specified - how do you decide whether buddy's hungry? That's no specified at all, so you have to make some assumptions (and document them) or ask your teacher to specify this.)
This is all pretty stupid, but then so is modelling this problem using a polymorphic hierarchy, so there you go....

inserting subclasses into a superclasses array in c++

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;