my program basically depends on setters to initialize the data in my object instances but I want to remove them and have constructors in place of the setters, Is there a way I can do this or can anybody provide me a reference?
Instantiate object
//Using SDL and standard IO
#include <SDL.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include <iomanip>
#include <archer.hpp>
#include <ctime>
#include <ArmouredArcher.hpp>
#include <RNGI.hpp>
using namespace std; //Declaring use of namespace std
void instantiateMuskateer();
int main(int argc, char* argv[])
{
//init muskateer object
instantiateMuskateer();
system("pause");
return 0;
}
Instantiation, Activity and destruction
void instantiateMuskateer()
{
Archer* Muskateer = new Archer();
Muskateer->setName("Brett");
delete Muskateer;
}
.hpp file
#ifndef _Archer_
#define _Archer_
#include <string>
class Archer
{
public:
inline Archer() :
name(""),
healthpoints(0),
baseDamage(0),
range(0)
{ ; } //All Member varials are in a known state
inline Archer(std::string name, int healthpoints, int baseDamage, int range) :
name(name),
healthpoints(healthpoints),
baseDamage(baseDamage),
range(range) //All member variables are in a known state
{
;
}
inline ~Archer() { ; } // empty destructor
inline std::string getName() { return name; }
inline void setName(std::string name) { this->name = name; }
inline int getHealthPoints() { return healthpoints; }
inline void setHealthPoints(int healthpoints) { this->healthpoints = healthpoints; }
inline int getBaseDamage() { return baseDamage; }
inline void setBaseDamage(int baseDamage) { this->baseDamage = baseDamage; }
inline int getRange() { return range; }
inline void setRange(int range) { this->range = range; }
/*std::string getName(); //getter for name
void setName(std::string name); //Set the name
int getHealthPoints();
void setHealthPoints(int healthpoints);
int getBaseDamage();
void setBaseDamage(int baseDamage);
int getRange();
void setRange(int range); */
protected:
private:
// copy constructor
Archer(const Archer& other) = delete;
// overload assignment operator
Archer& operator=(const Archer& other) = delete;
std::string name;
int healthpoints;
int baseDamage;
int range;
};
#endif
In your example, it is really simple, you just have to take the parameters you need in your constructor:
Archer(std::string n) :
name(n),
healthpoints(0),
baseDamage(0),
range(0)
{} //All Member varials are in a known state
And then you can simply do that:
void instantiateMuskateer()
{
Archer* Muskateer = new Archer("Brett");
delete Muskateer;
}
A few comments not related, but to improve your code. Writing inline is useless when you declare and implement your functions inside your class, the inline is implied. Also, if your destructor does nothing, you should not define it or use = default, that way you can enable some optimizations from the compiler.
Also, in your previous function i see no need to allocate the object on the heap, it is again a loss of performance and a source of error (such as forgetting to delete the object), allocate it on the stack:
void instantiateMuskateer()
{
Archer Muskateer("Brett");
// do your things
}
Or use a unique_ptr.
Related
I need to get in a vector the names of some cities as soon as they are created... In order to accomplish that I created a static vector for the class City, however when I try to compile my code I get the error
error: lvalue required as unary '&' operand
this->cities.push_back(&this);
^~~~
What am I doing wrong?
My code is the following...
#include <iostream>
#include <ctime>
#include <vector>
using namespace std;
class City
{
private:
string name;
static vector<City *> cities;
public:
string getName() { return name; }
City(string name) : name{name}
{
this->cities.push_back(&this);
};
~City(){};
} hongKong{"Hong Kong"}, bangkok{"Bangkok"}, macau{"Macau"}, singapura{"Singapura"}, londres{"Londres"}, paris{"Paris"}, dubai{"Dubai"}, delhi{"Delhi"}, istambul{"Istambul"}, kuala{"Kuala"}, lumpur{"Lumpur"}, novaIorque{"Nova Iorque"}, antalya{"Antalya"}, mumbai{"Mumbai"}, shenzen{"Shenzen"}, phuket{"Phuket"};
int main()
{
}
this is already a City* pointer, so drop the & from &this.
Also, don't forget to actually define the static vector object.
Also, you should account for the class' copy/move constructors and destructor, to make sure you don't miss adding pointers, or leave behind dangling pointers.
Try this:
#include <iostream>
#include <ctime>
#include <vector>
using namespace std;
class City
{
private:
string name;
static vector<City *> cities;
public:
string getName() { return name; }
City(string name) : name{name}
{
cities.push_back(this);
}
City(const City &src) : name{src.name}
{
cities.push_back(this);
}
City(City &&src) : name{std::move(src.name)}
{
cities.push_back(this);
}
~City()
{
cities.erase(std::find(cities.begin(), cities.end(), this));
}
};
vector<City *> City::cities;
City hongKong{"Hong Kong"}, bangkok{"Bangkok"}, macau{"Macau"}, singapura{"Singapura"}, londres{"Londres"}, paris{"Paris"}, dubai{"Dubai"}, delhi{"Delhi"}, istambul{"Istambul"}, kuala{"Kuala"}, lumpur{"Lumpur"}, novaIorque{"Nova Iorque"}, antalya{"Antalya"}, mumbai{"Mumbai"}, shenzen{"Shenzen"}, phuket{"Phuket"};
int main()
{
}
This question already has answers here:
Why does C++ allow us to surround the variable name in parentheses when declaring a variable?
(2 answers)
Closed 5 years ago.
Hello,
I'm trying to instantiate an anonymous object with a std::string variable 'name'. But intellisenen gives me error saying
E0291 no default constructor exists for class "Player" GoldGame e:\C++ Projects\Hello World\GoldGame\GoldGame.cpp 17
I have provided a constructor which can just take a std::string variable since other parameters are provided with default value.
Can you guys shed some light on this?
What confuses me even more is that when I change
Player(name);
to
Player a(name);
or to
Player("test");
then intellisense becomes totally fine with those.
GoldGame.cpp
#include "stdafx.h"
#include "Creature.h"
#include "Player.h"
#include <iostream>
#include <string>
int main()
{
std::cout << "Enter your name: ";
std::string name;
std::cin >> name;
Player(name);
return 0;
}
Creature.h
#pragma once
#include <string>
class Creature
{
public:
Creature(const std::string &name, const char symbol, const int health, const int damage, const int gold);
~Creature();
//getters
const std::string& getName() { return m_name; }
const char getSymbol() { return m_symbol; }
const int getHealth() { return m_health; }
const int getDamage() { return m_damage; }
const int getGold() { return m_gold; }
//health, gold and dead
void reduceHealth(const int healthMinus);
void addGold(const int gold);
bool isDead();
private:
std::string m_name;
char m_symbol;
int m_health;
int m_damage;
int m_gold;
};
Creature.cpp
#include "stdafx.h"
#include "Creature.h"
Creature::Creature(const std::string & name, const char symbol, const int health, const int damage, const int gold)
:m_name(name), m_symbol(symbol), m_health(health), m_damage(damage), m_gold(gold)
{
}
Creature::~Creature()
{
}
void Creature::reduceHealth(const int healthMinus)
{
m_health -= healthMinus;
}
void Creature::addGold(const int gold)
{
m_gold += gold;
}
bool Creature::isDead()
{
if (m_health>0)
{
return true;
}
else
{
return false;
}
}
Player.h
#pragma once
#include "Creature.h"
#include <string>
class Player :
public Creature
{
public:
Player(const std::string &name, const char symbol='#', const int health=10, const int damage=1, const int gold=0);
~Player();
const int getLevel() { return m_level; }
void levelUp();
bool hasWon();
private:
int m_level;
};
Player.cpp
#include "stdafx.h"
#include "Player.h"
Player::Player(const std::string & name, const char symbol, const int health, const int damage, const int gold)
:Creature(name,symbol,health,damage,gold)
{
}
Player::~Player()
{
}
void Player::levelUp()
{
++m_level;
}
bool Player::hasWon()
{
if (m_level>=20)
{
return true;
}
else
{
return false;
}
}
Player(name); does not do what you think it does. It declares a new variable name of type Player and calls a default constructor. If you want to instantiate an anonymous Player variable then you need to write
(Player(name));
// or
Player{name}; // list initialization since C++11
I have a stream class with following functions :
void writeInt(int value); //old function
void writeInt(int value, char* lable); //new function
we've used the writeInt() old function in lot of places. without changing the existing usage
I tried to replace the old function with the new function using following:
#define writeInt(x) writeInt(x,#x)
but it still calls the old functions not the new functions!.
Update:(working test-case)
// IStream.h
#include <stdio.h>
class IWStream {
public:
IWStream(char* path);
virtual ~IWStream();
virtual void writeInt( int iValue, char* szlable= 0 );
private:
FILE* _file;
};
//DataObject.h
class DataObject {
public:
DataObject(int value);
virtual ~DataObject(){};
void writeData(IWStream *stream);
private:
int _value;
};
//DataObject.cpp
#include "DataObject.h"
#include "IStream.h"
#define writeInt(x) writeInt(x,#x)
DataObject::DataObject(int value)
{
_value = value;
}
void DataObject::writeData(IWStream *stream)
{
stream->writeInt(_value);
}
//main.cpp
int main(){
IWStream stream("D://test.txt");
DataObject data(10);
data.writeData(&stream);
return 0;
}
I'm writing a program for a homework assignment. The program compiles and runs, but has a bad access error.
This is main.cpp
#include <iostream>
#include <string>
#include "Mammal.h"
#include "Dog.h"
#include "Horse.h"
#include "Pig.h"
#include "Cat.h"
using namespace std;
//Seed for ease of grading
const int SEED=100;
const int NUM_ANIMALS=5;
const int WEIGHT_LIMIT=150;
void MammalAssignment(const Mammal * new_Mammal, int choice, string newName);
void UserChoice(const Mammal * new_Mammal);
void ListAnimal(const Mammal *new_Mammal);
int main()
{
string newName, newWeight;
srand(SEED);
Mammal *new_Mammal[NUM_ANIMALS];
UserChoice(*new_Mammal);
for(int i=0; i<NUM_ANIMALS; i++)
ListAnimal(new_Mammal[i]);
//Program pauses for user input to continue
char exit_char;
cout<<"\nPress any key and <enter> to exit\n";
cin>>exit_char;
return 0;
}
void UserChoice(const Mammal * new_Mammal)
{
int choice;
bool choiceGood;
string newName;
for(int i=0;i<NUM_ANIMALS; i++){
choiceGood=false;
while(choiceGood==false)
{
cout<<"-Please choose a number 1-4 for the corresponding animal-\n"
<<"1-Dog\n2-Horse\n3-Pig\n4-Cat\n";
cin>>choice; //User choice
if(choice<=0 || choice >=5){
cout<<"Your choice is invalid\n\n";
continue;
}
choiceGood=true;
} //While loop
cout<<"\nPlease enter a name for the animal you have chosen(Ex. Fido).\n";
cin>>newName;
MammalAssignment(&new_Mammal[i], choice, newName);
} //For loop
}
void MammalAssignment(const Mammal * new_Mammal, int choice, string newName)
{
if(choice==1){
Dog newDog(rand()%(WEIGHT_LIMIT+1), newName);
new_Mammal=&newDog;
}
else if(choice==2){
Horse newHorse(rand()%(WEIGHT_LIMIT+1), newName);
new_Mammal=&newHorse;
}
else if(choice==3){
Pig newPig(rand()%(WEIGHT_LIMIT+1), newName);
new_Mammal=&newPig;
}
else if(choice==4){
Cat newCat(rand()%(WEIGHT_LIMIT+1), newName);
new_Mammal=&newCat;
}
}
void ListAnimal(const Mammal *new_Mammal)
{
cout<<"-------------------------\nName:"
<<new_Mammal->GetName()<<"\nWeight: "
<<new_Mammal->GetWeight();
}
Mammal.h
#ifndef MAMMAL_H
#define MAMMAL_H
using namespace std;
class Mammal
{
public:
Mammal(); //Default constructor
Mammal( int newWeight); //Parameterized constructor
void SetWeight(int newWeight);
virtual string GetName() const;
int GetWeight() const;
//virtual function to be defined by derived animal classes
virtual void Speak() const;
private:
int weight;
};
#endif
Mammal.cpp
#include <iostream>
#include <string>
#include "Mammal.h"
using namespace std;
Mammal::Mammal()
{
SetWeight(0);
cout<<"\nInvoking default Mammal Constructor\n";
}
Mammal::Mammal( int newWeight)
{
SetWeight(newWeight);
cout<<"\nInvoking parameterized Mammal Constructor\n";
}
void Mammal::SetWeight(int newWeight)
{
weight=newWeight;
}
int Mammal::GetWeight() const
{
return weight;
}
string Mammal::GetName() const
{}
void Mammal::Speak() const
{
cout<<"\nLadies and gentlemen, the mammal speaks...\n";
}
Dog.h
#ifndef DOG_H
#define DOG_H
#include "Mammal.h"
using namespace std;
class Dog: public Mammal
{
public:
Dog(); //Default constructor
Dog(const int& newWeight,const string& newName); //Parameterized constructor
void SetName(string newName);
string GetName() const;
//mammal virtual function
virtual void Speak() const;
private:
string name;
};
#endif
Dog.cpp
#include <iostream>
#include <string>
#include "Dog.h"
using namespace std;
//Default constructor
Dog::Dog()
{
cout<<"\nInvoking default Dog constructor\n";
}
//Parameterized constructor
Dog::Dog( const int& newWeight,const string& newName):Mammal(newWeight)
{
SetName(newName);
cout<<"\nInvoking parameterized Dog constructor.\n";
}
void Dog::SetName(string newName)
{
name=newName;
}
string Dog::GetName() const
{
return name;
}
//mammal virtual function
void Dog::Speak() const
{
Mammal::Speak();
cout<<"\nWoof!\n";
}
The other derived classes(horse, pig, and cat) are all identical to Dog. I'm getting a Exc_Bad_Access error when ListAnimals() gets to GetWeight(). As far as I can tell it's returning the right file type. Any help would be awesome
Your MammalAssignment function is returning a pointer to a local variable. Once the function returns, that memory (which was on the stack) is gone and you will crash when you access it as an object of the relevant mammal type.
You need to return a pointer to memory allocated using operator new, or possibly just an object instead of a pointer, assuming suitable copy semantics are implemented in your Mammal classes.
A revision (or initial self-education?)of memory management in C++ would be in order before you go any further. See also smart pointers, to avoid new/delete where possible and make your life easier.
Mammal *new_Mammal[NUM_ANIMALS];
You need to allocate memory using new !
Mammal *new_Mammal = new Mammal[NUM_ANIMALS];
Also I think your UserChoice function should take the pointer as a reference and not as a const value to be able to change the actual content.
I just moved from C to C++, and now work with lists.
I have a class called "message", and I need to have a class called "line",
which should have a list of messages in its properties. as I learned, the object's properties should be initialized in the constructor's initialization list, and i had the "urge" to initialize the messages list in addition to the rest of the properties (some strings and doubles). is that "urge" justified? does the list need to be initialized?
here is my code.
the purpose is to create an empty list of lines, and the constructor I'm talking about is the one in line.cpp
//-------------------
//Code for line.h:
//-------------------
#ifndef LINE_H_
#define LINE_H_
#include "message.h"
#include <string>
#include <list>
using namespace std;
namespace test
{
using std::string;
class Line
{
public:
// constractor with parameters
Line(const string& phoneStr, double callRate, double messageRate);
//function to get phone string
string getPhoneStr() const;
double getCallRate() const;
double getMessageRate() const;
double getLastBill() const;
void addMessage(const string& phoneStr);
private:
string mPhoneStr;
list<Message> mMessages;
double mMessageRate;
double mLastBill;
};
}
#endif /* LINE_H_ */
//-------------------
//Code for line.cpp:
//-------------------
#include "line.h"
namespace test
{
Line::Line(const string& phoneStr, double callRate, double messageRate)
: mPhoneStr(phoneStr), mCallRate(callRate), mMessageRate(messageRate),
mLastBill(0) {}
//getters:
string Line::getPhoneStr() const
{
return mPhoneStr;
}
double Line::getCallRate() const
{
return mCallRate;
}
double Line::getMessageRate() const
{
return mMessageRate;
}
double Line::getLastBill() const
{
return mLastBill;
}
}
//-------------------
//Code for message.h:
//-------------------
#ifndef MESSAGE_H_
#define MESSAGE_H_
#include <string>
namespace test
{
using std::string;
class Message
{
public:
// constractor with parameters
Message(const string& phoneStr);
//function to get phone string
string getPhoneStr() const;
//function to set new phone string
void setPhoneStr(const string& phoneStr);
private:
string mPhoneStr;
};
}
#endif /* MESSAGE_H_ */
//-----------------------------------------------------------------------
//---------------------
//code for message.cpp:
//---------------------
#include "message.h"
namespace test
{
Message::Message(const string& phoneStr) : mPhoneStr(phoneStr) {}
string Message::getPhoneStr() const
{
return mPhoneStr;
}
void Message::setPhoneStr(const string& phoneStr)
{
mPhoneStr = phoneStr;
}
}
The initialization list is for initializing any base classes and member variables. The body of the constructor is meant to run any other code that you need before the object can be considered initialized.
I'm having a hard time understanding your situation, but hopefully the above helps.
You don't have to do everything in the initialisation list. It's hard to tell without seeing some code, but it sounds like adding the messages would be better done in the body of the constructor.