How to use member of one class in another class constructor - c++

I have a class:
class Cave
{
private:
int no_of_rooms;
public:
vector<int>rooms;
Cave(int r);
Cave(){};
};
The constructor of Cave fills the vector rooms with random integers:
Cave::Cave(int r)
:no_of_rooms{ r }
{
int i = 0;
while (i<no_of_rooms)
{
rooms.push_back(randint(1, no_of_rooms));
++i;
}
}
I create another class:
class Player : public Cave
{
public:
Player(int *plyr)
:p_ptr{ plyr }
{
plyr = &rooms[0];
}
private:
int* p_ptr = nullptr;
};
This Player class seems to be a mess. I am trying to get access to the same rooms vector filled up by the Cave constructor.

I think you really should encapsulate Cave and not inherit from it. Try this.
cave.h
#include <vector>
#include <random>
class Cave
{
private:
int no_of_rooms;
public:
std::vector<int>rooms;
Cave(int r);
Cave(){};
};
inline int randint(int min, int max)
{
std::random_device device;
std::mt19937 engine(device());
std::uniform_int_distribution<int> dist(min, max);
return dist(engine);
}
cave.cpp
#include "cave.h"
Cave::Cave(int r)
:no_of_rooms{ r }
{
int i = 0;
while (i<no_of_rooms)
{
rooms.push_back(randint(1, no_of_rooms));
++i;
}
}
player.h
#include "cave.h"
class Player// : public Cave
{
public:
Player(int *plyr)
:p_ptr{ plyr }
{
cave = Cave(*plyr);
plyr = &cave.rooms[0];
}
private:
Cave cave;
int* p_ptr = nullptr;
};
I tried it using
#include "player.h"
int main(int argc, char* argv[])
{
int player_count = 2;
Player p(&player_count);
}
Also, I am not sure the unnecessary use of pointers in some of your code.

You may have a typo:
plyr = &rooms[0];
This sets the function argument, not the member.
You meant p_ptr = &rooms[0];?
But then why have a function argument at all. This makes no sense.
Unfortunately, you did not get around to telling us what you want to do, or what you want these classes to do, or what input you need to provide to the classes. So I cannot answer any further.

Related

Problem with Deck reset function in a Deck

I am currently working on making a program where a deck of 52 cards are displayed. You will be able to reset the deck, pick a card or exit the program. I have gotten the Card.h and Card.cpp parts done without any issue.
Card.h:
enum class Suit
{
Spades,
Hearts,
Diamonds,
Clubs
};
class Card
{
private:
int m_value;
Suit m_suit;
void display();
void set(int v, Suit s);
int getValue();
Suit getSuit();
};
Card.cpp:
#include "Card.h"
#include <iostream>
using namespace std;
Card::Card() :
m_value()
{
}
void Card::display()
{
if (m_value != 0)
{
cout << m_value; m_suit;
}
else
{
cout << "--";
}
}
void Card::set(int v, Suit s)
{
m_value = v;
m_suit = s;
}
int Card::getValue()
{
return m_value;
}
Suit Card::getSuit()
{
return Suit();
}
I have also managed to successfully write in the code for Deck.h, shown below:
#pragma once
#include "Card.h"
class Deck
{
public:
static const int c_numCards = 52;
private:
int m_cards[c_numCards];
int m_cardsLeft;
void reset();
void display();
bool pickCard(Card& card);
};
However, I have been struggling with the reset method, shown below:
#include "Deck.h"
#include "Card.h"
#include <iostream>
Deck::Deck() :
m_cards{},
m_cardsLeft()
{
}
void Deck::reset()
{
//This method initializes the deck setting all card values and suits in order of value (1’s in each suit, then 2’s,etc)//
int i = 1;
for(int j = 0; j < 14; j++)
{
m_cards[j].set(i, Suit::Spades);
m_cards[j + 1].set(i, Suit::Hearts);
m_cards[j + 2].set(i, Suit::Diamonds);
m_cards[j + 3].set(i, Suit::Clubs);
j = j + 4;
}
}
void Deck::display()
{
//This method displays the entire deck using the display() method//
}
bool Deck::pickCard(Card& card)
{
//This method passes in a "blank" card object. It chooses a single card on random, copying it into the object and returns it true. When its picked, the card is no longer capable of being chosen in the deck.
//however, if there are no more cards left to be chosen, it will return false.//
}
as clarification, I haven't done the other methods yet since my way of doing stuff forces me to focus on one part first before anything else.
I mainly want help for the reset method, although help for the two other methods would be appreciated. I haven't included main since I seek to figure that part out on my own.
I also want to clarify, this does not have any vectors. It specifically needs arrays, unscoped and scoped enums
I have attempted various ways of rendering the code, such as with if statements, but so far only this one has proven successful. everything works fine, but Visual Studios tells me that int statements dont work, and whenever I attempt to change it gives me new errors.

C++, How to call a child method in the parent class

I have two classes in my project:
Style
Line
In which, Line is the child of Style, so Line inherits from Style.
I need that when I call a method of the class Style (the parent) from Line (the child), the method of Style calls a method of the child, for your better understanding here is the code:
Line calls the Style function --> Style calls the Line function
Style.h:
#pragma once
class Style
{
public:
void set_size(int width, int height);
protected:
int width, height;
};
Style.cpp:
#include "Style.h"
void Style::set_size(int width, int height)
{
Style::width = width;
Style::height = height;
}
Line.h:
#pragma once
#include "Style.h"
#include <vector>
using namespace std;
class Line : public Style
{
public:
void draw();
vector <vector<char>> matrix;
};
Line.cpp:
#include "Line.h"
void Line::draw()
{
vector <char> row;
int i, j;
for (i = 0; i < Line::height; i++)
{
row.clear();
for (j = 0; j < Line::height; i++)
{
row.push_back('-');
}
Line::matrix.push_back(row);
}
}
Main.cpp:
#include <iostream>
#include "Line.h"
using namespace std;
int main()
{
Line line;
line.set_size(10, 10);
}
Obviously, this code for now does nothing much, it only modifies Style variables.
What I expect is that when I call set_size(), in addition to changing the value of the variables width and height, it will also change the size of the matrix
I don't know how to do what I said before.
I don't even know if it is a good method that Line is a child of Style, in any case other solutions that do not include inheritance are welcome.
Thanks in advance.
You need virtual functions, it would seem that set_size is the one that should be virtual, but this is not the only way to do it.
class Style
{
public:
virtual void set_size(int width, int height);
virtual ~Style() {}
protected:
int width, height;
};
class Line : public Style
{
public:
void draw();
virtual void set_size(int width, int height)
{
Style::set_size(width, height);
... // some code to resize matrix
}
vector <vector<char>> matrix;
};
But I question if this is good design, Style should be an attribute of Line (i.e. a member variable). Inheritance doesn't seem appropriate here, which is why you are struggling to write the code.
I tried to have implementation and declaration in the same file. but you can structure it as you may feel good for your project.
#include <iostream>
#include <vector>
using namespace std;
class Line;
class Style
{
public:
void set_size(int width, int height){
w = width;
h = height;
}
void print(){
cout << w << ", " << h << endl;
}
friend class Line;
protected:
int w, h;
};
class Line : public Style
{
public:
void draw(){
vector <char> row;
int i, j;
for (i = 0; i < w; i++)
{
row.clear();
for (j = 0; j < h; i++)
{
row.push_back('-');
}
matrix.push_back(row);
}
}
vector<vector<char>> matrix;
};
int main()
{
Line line;
line.set_size(10, 10);
line.print();
line.set_size(20, 20);
line.print();
}
We can just overload set_size within Line and call the other set_size from there and also the draw function to recreate the matrix.
This solution provides simple static polymorphism, that means a Line cannot be assigned to a Style - you probably do not need this? So the compiler always statically at compile-time knows, which class an object really is and can call the correct member function. No virtual member functions are needed.
There also were bugs in the draw function, which I corrected below.
The changes to your code are marked with a comment in the following.
// Line.h
#pragma once
#include "Style.h"
#include <vector>
using namespace std;
class Line : private Style // use private inheritance for static polymorphism
{
public:
void draw();
void set_size(int width, int height); // overload set_size (override only for virtual functions)
vector <vector<char>> matrix;
};
// Line.cpp
#include "Line.h"
void Line::set_size(int width, int height)
{
Style::set_size(width, height); // call set_size() function of style
draw(); // draw() to set matrix to new size
}
void Line::draw()
{
Line::matrix.clear(); // clear matrix, if draw() is called more than once
vector <char> row;
int i, j;
for (i = 0; i < Line::height; i++)
{
row.clear();
for (j = 0; j < Line::width; j++) // use Line::width and j++ (there were bugs)
{
row.push_back('-');
}
Line::matrix.push_back(row);
}
}
// Main.cpp
#include <iostream>
#include "Line.h"
using namespace std;
int main()
{
Line line;
line.set_size(10, 10); // calls the enhanced Line::set_size
// The following compilation errors (when the comments are removed) are good, as they prevent wrong usage of the current class definitions
// Style style = line; // would give error, as we have private inheritance and want to prevent 'slicing' and the calling of the wrong member functions; if a Line should be able to be assigned to a Style, you need public dynamic inheritance and virtual functions, as provided in other answers. If you do not need to assign a Line to a Style, use the simpler implementation from this answer.
// Style* stylepointer = &line; // also would give an error
}
Optionally draw() and matrix can be made private in Line.
If you need to call functions (other than set_size) of Style directly, you can use public inheritance, but make all constructors (including default/copy/move) of Style protected, so that only children like Line can call them. This would also prevent assignments of Line to Style.
EDIT: I'm completely changing the original answer since the question was modified too. If I get it right, you would like line.set_size(...) to call first the parent method and then to update the matrix. You cannot do that, because only one method will be called, and not both of them what you could do is add a set_size method for Line that calls Style's one.
line.h should be changed like this:
class Line : public Style
{
public:
void draw();
void set_size(int width, int height);
vector<vector<char>> matrix;
};
and you should append this to line.cpp:
void Line::set_size(int width, int height)
{
// call parent method
Style::set_size(width, height);
// now update matrix
int i, j;
matrix.resize(height);
for (auto &row : matrix)
{
row.resize(width);
}
}
Hope it helps!
Base function must be virtual for runtime inheritance.
as follows example
class base {
public:
virtual void print()
{
cout << "print base class\n";
}
void show()
{
cout << "show base class\n";
}
};
class derived : public base {
public:
void print()
{
cout << "print derived class\n";
}
void show()
{
cout << "show derived class\n";
}
};
int main()
{
base *bptr;
derived d;
bptr = &d;
// Virtual function, binded at runtime
bptr->print();
// Non-virtual function, binded at compile time
bptr->show();
return 0;
}

C++ object orientated issue

I am trying to learn C++ OOP and I made the follwing code:
main.cpp
#include <iostream>
#include <string>
#include "monster.h"
using namespace std;
int main(int argc, char** argv) {
Monster monster("Wizard",150,50);
Monster monster2("Gorgoyle",450,15);
cout << monster2.getHealth() << endl;
monster.attack(monster2);
cout << monster2.getHealth() << endl;
}
monster.h
#ifndef MONSTER_H
#define MONSTER_H
#include <iostream>
#include <string>
using namespace std;
class Monster
{
public:
Monster(string name_, int health_, int damage_);
~Monster();
int attack(Monster opponet);
int getHealth();
string name;
int damage;
int health = 0;
int getDamage();
void setHealth(int health_);
void setDamage(int damage_);
void setName(string name);
void doDamageToOpponent(Monster opponent);
string getName();
};
#endif
monster.cpp
#include "monster.h"
Monster::Monster(string name_, int health_, int damage_) {
health = health_;
setDamage(damage_);
setName(name_);
}
Monster::~Monster() { }
int Monster::attack(Monster opponent) {
doDamageToOpponent(opponent);
}
void Monster::doDamageToOpponent(Monster opponent) {
int newHealth = opponent.getHealth() - this->getDamage();
opponent.setHealth(newHealth);
}
int Monster::getHealth() {
return health;
}
int Monster::getDamage() {
return damage;
}
void Monster::setHealth(int health_) {
health = health_;
}
void Monster::setDamage(int damage_) {
this->damage = damage_;
}
void Monster::setName(string name_) {
this->name = name_;
}
string Monster::getName() {
return name;
}
Now my problem is that, when I run this code I expect to have monster2 object to have 400 health left, but it is still 450 :S
What must be done here in order to to so? I noticed that it can be 400 in doDamageToOppoenet but when it leaves that block, then it is still 450. Please help me! Thanks.
You're passing objects by value:
void Monster::doDamageToOpponent(Monster opponent) <- This should be by reference
int Monster::attack(Monster opponent) <- idem
that means: you're creating a new copy of the Monster object you meant to deal damage to in the functions you're calling, and then actually dealing that copy damage but leaving the original old object with the value untouched.
Signatures as follows would work instead:
void Monster::doDamageToOpponent(Monster& opponent)
int Monster::attack(Monster& opponent)
If you want to learn more about this, something to read on: Passing stuff by reference and Passing stuff by value
The reason is that functions attack and doDamageToOpponent are taking copies of arguments, because you pass them by value. What happenes then is you change the copies of passed Monsters inside functions. After functions return, these copies die (as they are local to functions) and nothing happens to original, interested parties.
Try instead pass the argument by reference. Reference works as if it was the original variable. Consider:
int a = 0;
int &refa = a; /* refa acts as real "a", it refers to the same object "a" */
int b = a; /* this is your case */
b = 6; /* b will be changed, but "a" not */
refa = 6; /* a is changed, really "a", refa is just different name for "a" */
Try:
int Monster::attack( Monster &opponent){
doDamageToOpponent( opponent);
}
void Monster::doDamageToOpponent( Monster &opponent){
int newHealth = opponent.getHealth() - this->getDamage();
opponent.setHealth( newHealth);
}
You are passing the opponent by value, i.e., the function:
int Monster::attack(Monster opponent);
will actually receive a copy of the opponent and modify that copy. Every time you have a function that modifies some object you need to pass the object to be modified by reference or pass a pointer to it, e.g.,
int Monster::attack(Monster& opponent);
or
int Monster::attack(Monster* opponent);
I recommend using const T& for input parameters and T* for output parameters, so in this case, the latter form. The reason why I recommend the latter for output parameters is because it makes it more explicit to the caller:
monster.attack(&monster2); // passing a pointer: monster2 will be modified.

Declaring a Class C++

I am struggling knowing how to create a class. I want to create a "Player" class and all I want to do is pass in the name while I'll have the other variables start at 0 until they are updated when a game is run (later in the program)
Player::Player(string name_in)
{
name = name_in;
int numOfWins = 0;
int numOfLoses = 0;
int numOfDraws = 0;
int totalMatches = 0;
}
Right now there are lots of errors around numOfWins, numOfLoses, numOfDraws and totalMatches. What can I do to fix this?
Perhaps the error is in your int ... part of assignments, which essentially creates a new local variable in a constructor.
Try this version:
#include <string>
using namespace std;
class Player
{
string name;
int numOfWins;
int numOfLoses;
int numOfDraws;
int totalMatches;
public:
Player(string name_in)
{
name = name_in;
numOfWins = 0;
numOfLoses = 0;
numOfDraws = 0;
totalMatches = 0;
}
};
You should declare other instance variables in the class declaration, rather than declaring them as locals (which is completely useless).
// This part goes in the header
class Player {
string name;
int numOfWins;
int numOfLoses;
int numOfDraws;
int totalMatches;
public:
Player(string name_in);
};
Now in the constructor you could use initialization lists:
// This part goes into the CPP file
Player::Player(string name_in)
// Initialization list precedes the body of the constructor
: name(name_in), numOfWins(0), numOfLoses(0), numOfDraws(0), totalMatches(0) {
// In this case, the body of the constructor is empty;
// there are no local variable declarations here.
}
Kinda vague, but I'll take a crack at it. You Probably want:
class Player{
string name;
int numOfWins;
int numOfLosses;
int numOfDraws;
int totalMatches;
Player(string name_in)
};
Player::Player(string name_in){
name = name_in;
numOfWins = 0;
numOfLosses = 0;
numOfDraws = 0;
totalMatches = 0;
}
Haven't used C++ in a while, so this may be faulty.
The errors you get, at least from the snippet you posted are caused for you can't declare variables in constructor - you declare them in class body and initialize in constructor or using another function.
#include <string>
class Player {
public:
Player( std::string const& name_in) : name( name_in),
numOfWins(), numOfLoses(),
numOfDraws(), totalMatches()
{} // constructor
// will initialize variables
// numOfWins() means default
// initialization of an integer
private:
std::string name;
int numOfWins;
int numOfLoses;
int numOfDraws;
int totalMatches;
};
usage:
int main() {
Player( "player_one");
return 0;
}

Multilevel inheritance/polymorphism and virtual function

I have a multilevel inheritance (from Ship class -> MedicShip class -> Medic class) with virtual function code as below. I suppose the result should be :
Medic 10
Medic 10
But it generated strange result. On the other hand, if I only use one level inheritance (from Ship class -> Medic class without MedicShip class in between) the result will be OK. Could you find my mistake please? Many thank....
#ifndef FLEET_H
#define FLEET_H
#include <string>
#include <vector>
using namespace std;
class Ship
{
public:
Ship(){};
~Ship(){};
int weight;
string typeName;
int getWeight() const;
virtual string getTypeName() const = 0;
};
class MedicShip: public Ship
{
public:
MedicShip(){};
~MedicShip(){};
string getTypeName() const;
};
class Medic: public MedicShip
{
public:
Medic();
};
class Fleet
{
public:
Fleet(){};
vector<Ship*> ships;
vector<Ship*> shipList() const;
};
#endif // FLEET_H
#include "Fleet.h"
#include <iostream>
using namespace std;
vector<Ship*> Fleet::shipList() const
{
return ships;
}
int Ship::getWeight() const
{
return weight;
}
string Ship::getTypeName() const
{
return typeName;
}
string MedicShip::getTypeName() const
{
return typeName;
}
Medic::Medic()
{
weight = 10;
typeName = "Medic";
}
int main()
{
Fleet fleet;
MedicShip newMedic;
fleet.ships.push_back(&newMedic);
fleet.ships.push_back(&newMedic);
for (int j=0; j< fleet.shipList().size(); ++j)
{
Ship* s = fleet.shipList().at(j);
cout << s->getTypeName() << "\t" << s->getWeight() << endl;
}
cin.get();
return 0;
}
You haven't created any instances of class Medic. Did you mean to say
Medic newMedic;
instead of
MedicShip newMedic;
perhaps? So, the Medic constructor isn't being called and weight and typeName aren't being initialized.
~Ship(){};
The first mistake is right here. This destructor should be virtual if you want to delete derived class objects through base class pointer.