Error using unique_ptr to access functions in subclasses - c++

My aim with this program is to have a vector of objects describing various types of vehicles. The base class will have a user defined type variable, while each of the subclasses will have a default value as type(eg Van, Bus, etc.). After some searching I found that the best way to use both base and derived classes in a vector is to use a vector of pointers. Here is a simplified version of the code I wrote:
#include <iostream>
#include <string>
#include <vector>
#include <memory>
using namespace std;
class Vehicle
{
public:
Vehicle();
~Vehicle();
virtual void Initialize(string a,string b, int c, int d, int e, string f);
void print_details();
void get_yard(int x);
string type;
protected:
string make_and_model;
int max_pass;
int max_load;
int yard;
string date;
};
class Lorry : public Vehicle
{
public:
void Initialize(string a="Lorry", string b, int c, int d, int e, string f);
};
int i,count;
std::vector<std::unique_ptr<Vehicle>> arr;
Vehicle::Vehicle()
{
std::cout << "New Entry created." << std::endl;
}
Vehicle::~Vehicle()
{
std::cout << "Entry closed." << std::endl;
}
void Vehicle::Initialize(string a,string b, int c, int d, int e, string f)
{
type=a;
make_and_model=b;
max_pass=c;
max_load=d;
yard=e;
date=f;
}
void Lorry::Initialize(string a="Lorry", string b, int c, int d, int e, string f)
{
make_and_model=b;
max_pass=c;
max_load=d;
yard=e;
date=f;
}
void Vehicle::print_details()
{
std::cout << "Vehicle Type:"<< type << std::endl;
std::cout << "Make And Model:"<< make_and_model << std::endl;
std::cout << "Maximum Passengers:"<< max_pass << std::endl;
std::cout << "Maximum Load Capacity(in Kg):"<< max_load << std::endl;
std::cout << "Located Yard:"<< yard << std::endl;
std::cout << "Date of Arrival(dd-MM-YYYY):"<< date <<"\n"<< std::endl;
}
void new_objects()
{
std::cout<<"How many entries?"<<std::endl;
std::cin>>count;
std:: cout<<"The open yards are: Yard 1, Yard 2, Yard 3"<<std::endl;
for (i = 0; i < count; i++)
{
int vc_choice;
std::cout<<"What is the vehicle type?"<<std::endl;
std::cout<<"1.Lorry\n6.Other\n";
std::cin>>vc_choice;
string a;
string b;
int c;
int d;
int e;
string f;
switch (vc_choice)
{
case 1:
arr.emplace_back(new Lorry());
std::cout<<"Enter the vehicle make and model: "<<std::endl;
std::cout << "WARNING: Do NOT use spaces, use underscores." << std::endl;
std::cin>>b;
std::cin.clear();
std::cout<<"Enter the maximum passenger capacity: "<< std::endl;
std::cin>>c;
std::cin.clear();
std::cout<<"Enter the maximum load capacity(Kgs): "<<std::endl;
std::cin>>d;
std::cout<<"Enter the yard number"<<std::endl;
std::cin>>e;
std::cout<<"Enter the date of arrival(dd-mm-yyyy): "<<std::endl;
std::cin>>f;
arr.Initialize(a,b,c,d,e,f);
break;
default:
arr.emplace_back(new Vehicle());
std::cout<<"Enter the vehicle type: "<<std::endl;
std::cout << "WARNING: Do NOT use spaces, use underscores." << std::endl;
std::cin>>a;
std::cout<<"Enter the vehicle make and model: "<<std::endl;
std::cout << "WARNING: Do NOT use spaces, use underscores." << std::endl;
std::cin>>b;
std::cin.clear();
std::cout<<"Enter the maximum passenger capacity: "<< std::endl;
std::cin>>c;
std::cin.clear();
std::cout<<"Enter the maximum load capacity(Kgs): "<<std::endl;
std::cin>>d;
std::cout<<"Enter the yard number"<<std::endl;
std::cin>>e;
std::cout<<"Enter the date of arrival(dd-mm-yyyy): "<<std::endl;
std::cin>>f;
arr.Initialize(a,b,c,d,e,f));
break;
}
}
}
void print_all()
{
for (int a= 0; a<5; i++)
{
arr[a].print_details();
}
}
int main()
{
new_objects();
print_all();
return 0;
}
Trying to compile it I get this error:
[test unique_ptr.cpp 2021-04-24 06:59:33.521]
,,test unique_ptr.cpp: In function 'void new_objects()':
test unique_ptr.cpp:122:29: error: 'class std::vector<std::unique_ptr<Vehicle> >' has no member named
'Initialize'
122 | arr.Initialize(a,b,c,d,e,f);
| ^~~~~~~~~~
test unique_ptr.cpp:151:29: error: 'class std::vector<std::unique_ptr<Vehicle> >' has no member named
'Initialize'
151 | arr.Initialize(a,b,c,d,e,f));
| ^~~~~~~~~~
test unique_ptr.cpp: In function 'void print_all()':
test unique_ptr.cpp:162:16: error: '__gnu_cxx::__alloc_traits<std::allocator<std::unique_ptr<Vehicle> >,
std::unique_ptr<Vehicle> >::value_type' {aka 'class std::unique_ptr<Vehicle>'} has no member named
'print_details'
162 | arr[a].print_details();
| ^~~~~~~~~~~~~
I've tried using the arrow operator but this still doesn't work, as arr is not a pointer. How can I get the program to run?

Three types of errors.
You can't use default value for the 1st argument and leaving the rest alone. Meaning you cannot write void Initialize(string a="Lorry", string b, int c, int d, int e, string f);. You can write:
void Initialize(string a, string b, int c, int d, int e, string f)
or
void Initialize(string a, string b, int c, int d, int e, string f="Lorry")
or
void Initialize(string a, string b, int c, int d, int e = 0, string f="Lorry")
& the second one is you can't use . to access the method from a pointer, instead you need to use ->. read the thread. The third one is you are calling Initialize from a vector. You need to specify the index to indicate its element. You need to write:
arr[arr.size() - 1]->Initialize(a, b, c, d, e, f);
......
arr[a]->print_details();

Related

error: invalid use of non-static member function C++

I have two classes that I want to chain-call (main -> execute -> calculate). However, the issue is that when I use:
&calculate::addition;
Addition will not be called even if the compiler doesn't return any error. If I try to remove the reference to
calculate::addition;
The compiler returns error
error: invalid use of non-static member function ‘void calculate::addition(double&, double, double)’
case 'a' : *calculate::addition; break;
^~~~~~~~
Tried using static before void with the same result as using reference.
#include <iostream>
class execute{
public:
void exec(char);
}jalan;
class calculate {
public:
void addition(double&, double, double);
void substraction(double&, double, double);
void multiply(double&, double, double);
void division(double&, double, double);
};
int main(void){
static double a, b;
static double result;
std::cout << "Type a, b, c, or d" << std::endl;
std::cout << "a. Addition\nb. Substraction\nc. Multiply\nd. Division" << std::endl;
std::cout << "Your Input: ";
static char option;
option = getchar();
std::cout << "First value: ";
std::cin >> a;
std::cout << "Next value: ";
std::cin >> b;
jalan.exec(option);
std::cout << result << std::endl;
return 0;
}
void execute::exec (char option){
switch(option){
case 'a' : &calculate::addition; break;
case 'b' : &calculate::substraction; break;
case 'c' : &calculate::multiply; break;
case 'd' : &calculate::division; break;
}
}
void calculate::addition(double& result, double a, double b){
result = a+b;
}
void calculate::substraction(double& result, double a, double b){
result = a-b;
}
void calculate::multiply(double& result, double a, double b){
result = a*b;
}
void calculate::division(double& result, double a, double b){
result = a/b;
}
You have several issues in your code. Lets start:
error: invalid use of non-static member function ‘void calculate::addition(double&, double, double)’
case 'a' : *calculate::addition; break;
This means you have to create an instance of calculate or mark the method with static like static void addition(double&, double, double);
So change your class to
class calculate {
public:
static void addition(double&, double, double);
static void substraction(double&, double, double);
static void multiply(double&, double, double);
static void division(double&, double, double);
};
The next issue is that in your switch statement you only create pointers to functions
void execute::exec (char option){
switch(option){
case 'a' : &calculate::addition; break;
case 'b' : &calculate::substraction; break;
case 'c' : &calculate::multiply; break;
case 'd' : &calculate::division; break;
}
}
This never executes a function, but only creates a function pointer which is discarded right away.
In order to get your code to work, consider this code (note the comments in the code, which explain changes needed):
#include <iostream>
class execute
{
public:
void exec(char, double&, double, double);
}jalan;
class calculate {
public: // added static keyword so you do not need to create a class instance
static void addition(double&, double, double);
static void substraction(double&, double, double);
static void multiply(double&, double, double);
static void division(double&, double, double);
};
int main(void){
static double a, b;
static double result;
std::cout << "Type a, b, c, or d" << std::endl;
std::cout << "a. Addition\nb. Subtraction\nc. Multiply\nd. Division" << std::endl;
std::cout << "Your Input: ";
static char option;
option = getchar();
std::cout << "First value: ";
std::cin >> a;
std::cout << "Next value: ";
std::cin >> b;
jalan.exec(option, result, a, b); // you need to pass the arguments which you want to use and modify
std::cout << result << std::endl;
return 0;
}
void execute::exec (char option, double& res, double a, double b){
switch(option){ // changed the function pointers to actual calls to the functions
case 'a' : calculate::addition(res, a, b); break;
case 'b' : calculate::substraction(res, a, b); break;
case 'c' : calculate::multiply(res, a, b); break;
case 'd' : calculate::division(res, a, b); break;
}
}
void calculate::addition(double& result, double a, double b){
result = a+b;
}
void calculate::substraction(double& result, double a, double b){
result = a-b;
}
void calculate::multiply(double& result, double a, double b){
result = a*b;
}
void calculate::division(double& result, double a, double b){
result = a/b;
}
Hope this helps understanding your problems.
To call any method in class calculate you have to declare a variable first then call the method for example:
calculate c;
double a,b,res;
c.addition(a,b,res);
or you define the methods as static functions, in that case the calling will be like that
calculate::addition(a,b,res);

setters function inside constructor c++

I'm trying to use a setter function inside of a constructor, which I've never done before. It's giving me the following error:
[Error] no match for call to '(Laptop) (const char [5], const char [3], int, int)'
well do i need to write the setter function too ? i mean outside the constructor ? i mean like this
void Laptop::setBrand(char a[])
{
brand=a;}
I think the error is in the second constructor, that takes four arguments, but I'm not able to find it.
Here is the code:
#include <iostream>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
using namespace std;
class Laptop{
private:
char brand[10];
char processor[10];
int ram;
int hardDrive;
public:
void setBrand(char Bra[]);
void setProcessor(char Pro[]);
void setRam(int Ram);
void setHardDrive(int HDrive);
char *getBrand();
char *getProcessor();
int getRam();
int getHardDrive();
Laptop();
Laptop(char [],char [],int ,int );
};
Laptop::Laptop(){
cout<<"Default constructor called...\n";
strcpy(brand,"None");
strcpy(processor,"None);
ram=0;
hardDrive=0;
}
i think the error is in the constructor
Laptop::Laptop(char Bra[],char Pro[],int Ram,int HDrive)
{
cout<<"Parameterized constructor called...\n";
setBrand(Bra );
setProcessor(Pro );
setRam(Ram);
setHardDrive(HDrive);
}
char *Laptop::getBrand()
{
return brand;
}
char *Laptop::getProcessor()
{
return processor;
}
int Laptop::getRam()
{
return ram;
}
int Laptop::getHardDrive()
{
return hardDrive;
}
int main()
{
Laptop laptopObj1;
Laptop laptopobj1("Dell","i5",4,500);
cout<<"Brand :"<<laptopObj1.getBrand()<<"\n";
cout<<"Processor :"<<laptopObj1.getProcessor()<<"\n";
cout<<"Ram :"<<laptopObj1.getRam()<<"\n";
cout<<"HardDrive :"<<laptopObj1.getHardDrive()<<"\n";
cout<<"Brand :"<<laptopObj2.getBrand()<<"\n";
cout<<"Processor :"<<laptopObj2.getProcessor()<<"\n";
cout<<"Ram :"<<laptopObj2.getRam()<<"\n";
cout<<"HardDrive :"<<laptopObj2.getHardDrive()<<"\n";
}
You have alot of errors here..
Laptop laptopObj1,laptopObj2;
...
laptopObj2("Dell","i5", 4, 500);
You cant use the constructor twice. You used the constructor Laptop() in the first line for both of the object, and then tried to use the second constructor for laptopObj2.
You can change the second line to:
laptopObj2 = Laptop("Dell","i5", 4, 500);
Or even better to define it there:
Laptop laptopObj1;
....
Laptop laptopObj2("Dell","i5", 4, 500);
Another problem is inside your Laptop() constructor definition:
Laptop::Laptop(char Bra[],char Pro[],int Ram,int HDrive)
{
.....
setBrand(Bra []); // Remove the []
setProcessor(Pro []); // Remove the []
....
}
And one more problem: You have no definitions for some functions of the class:
void setBrand(char Bra[]);
void setProcessor(char Pro[]);
void setRam(int Ram);
void setHardDrive(int HDrive);
void display();
EDIT:
One of the objects of c++ is std::string (#include <string>). You can use it instead of char str[]- just simpler way to declare strings in c++. For example, in your case:
/* Replace this: */
char brand[10];
char processor[10];
void setBrand(char Bra[]);
void setProcessor(char Pro[]);
char *getBrand();
char *getProcessor();
/* With this: */
string brand;
string processor;
void setBrand(const string &Bra);
void setProcessor(const string &Pro);
string getBrand();
string getProcessor();
You are passing two const char* as parameter, so you should change this :
Laptop::Laptop(char Bra[],char Pro[],int Ram,int HDrive)
to this:
Laptop::Laptop(const char* ,const char* ,int Ram,int HDrive)
You really should use std::string rather than char[].
On the question of constructors, there is no need to call setters, as the following code demonstrates. C++ has a shortcut for that capability. I have used std::string and fixed all typos.
#include <iostream>
#include <string>
using namespace std;
class Laptop
{
private:
string brand;
string processor;
int ram;
int hardDrive;
public:
void setBrand(string Bra);
void setProcessor(string Pro);
void setRam(int Ram);
void setHardDrive(int HDrive);
string getBrand();
string getProcessor();
int getRam();
int getHardDrive();
Laptop();
Laptop(string, string, int, int);
};
Laptop::Laptop()
: brand("None")
, processor("None")
, ram(0)
, hardDrive(0)
{
cout << "Default constructor called...\n";
}
Laptop::Laptop(string Bra, string Pro, int Ram, int HDrive)
: brand(Bra)
, processor(Pro)
, ram(Ram)
, hardDrive(HDrive)
{
cout << "Parameterized constructor called...\n";
}
string Laptop::getBrand()
{
return brand;
}
string Laptop::getProcessor()
{
return processor;
}
int Laptop::getRam()
{
return ram;
}
int Laptop::getHardDrive()
{
return hardDrive;
}
int main()
{
Laptop laptopObj1;
Laptop laptopObj2("Dell", "i5", 4, 500);
cout << "Brand :" << laptopObj1.getBrand() << "\n";
cout << "Processor :" << laptopObj1.getProcessor() << "\n";
cout << "Ram :" << laptopObj1.getRam() << "\n";
cout << "HardDrive :" << laptopObj1.getHardDrive() << "\n";
cout << "Brand :" << laptopObj2.getBrand() << "\n";
cout << "Processor :" << laptopObj2.getProcessor() << "\n";
cout << "Ram :" << laptopObj2.getRam() << "\n";
cout << "HardDrive :" << laptopObj2.getHardDrive() << "\n";
}
Mike

swap user input in C++

I wish to create a constructor which takes input value from user, i.e value of a and b and then I wish to use these values in another function swap. This is more of general example. I wish to know where my concept is wrong.
#include <iostream>
using namespace std;
class swap_value
int a,b;
public:
swap_value()
{
cout<<"enter two numbers to swap";
cout<<"value of a is:";
cin>>a;
cout<<"value of b is:";
cin>>b;
}
void swap(int &a,int &b)
{
int temp=a;
a=b;
b=temp;
cout<<"value of a is :"<<a;
cout<<"value of b is :"<<b;
}
};
int main() {
swap_value obj;
obj.swap();
return 0;
}
#include <iostream>
using namespace std;
class swap_value {
int a,b;
public:
swap_value()
{
cout<<"enter two numbers to swap";
cout<<"value of a is:";
cin>>a;
cout<<"value of b is:";
cin>>b;
}
void swap(int &a,int &b)
{
int temp=a;
a=b;
b=temp;
cout<<"value of a is :"<<a;
cout<<"value of b is :"<<b;
}
};
int main() {
swap_value obj;
obj.swap();
return 0;
}
The thing that you should know is that all members of a class are accessible to all the methods of your class. So they don't need to be passed as parameters. The code you wrote doesn't compile (include error messages next time) because SwapValue doesn't have a method called swap() that takes no parameters.
Here is your code that does what you want it to. The change that I made was simply to make SwapValues::swap() take no parameters. Also, it is common practice to use UpperCamelCase for class names in C++. Indeed, it took me more time than it should have to notice that swap_values(){...} was your constructor for that reason.
#include <iostream>
using namespace std;
class SwapValues {
int a,b;
public:
SwapValues()
{
cout<<"enter two numbers to swap";
cout<<"value of a is:";
cin>>a;
cout<<"value of b is:";
cin>>b;
}
void swap()
{
int temp=a;
a=b;
b=temp;
cout<<"value of a is :"<<a << std::endl;
cout<<"value of b is :"<<b << std::endl;
}
};
int main() {
SwapValues sv;
sv.swap();
return 0;
}
Edit
To respond to the follow-up general question underlying the problem, the reason you are confused is because you are not sure about how the function gets access to a and b.
The short version is that methods of a class have built in access to all the attributes of the class.
The long version is that the instance of the class gets implicitly passed to methods of the class as an implicit parameter (called this in C++). So all functions of a class MyClass like
int MyClass::my_function( --parameters-- )
become
int MyClass::my_function(MyClass* this, --parameters--)
and the compiler, when it compiles code of such a function, sees
some_var = 1234;
will check firs if the function has a local variable or a local static variable or a parameter called some_var, and if there isn't, it will see if
this->some_var = 1234;
that is, it will check if `MyClass has an attribute called some_var.
In your case, in the working code we have
int temp = a;
so the compiler looks: is there a local variable called a, no local variable, is there a parameter called a, nope, next, what about this->a, the class does have an attribute called a so that's what we use.
So you always pass parameters, is the answer to your question but in the example of your function, that is done automatically. That's good because if you add an attribute to your class, you don't have to alter all the methods of your class to take an extra parameter, all the methods of the class will already have it.
In your first example, in fact, you should run this piece of code. It will show what I mean.
#include <iostream>
using namespace std;
class SwapValues {
public:
int a,b;
SwapValues()
{
a = 1;
b = 2;
}
void wrong_method(int &a, int &b)
{
std::cout << "wrong_method : "
<< "a = " << a
<< ", b = " << b
<< ", this->a = " << this->a
<< ", this->b = " << this->b << std::endl;
}
void right_method(int &param_1, int& param_2)
{
std::cout << "right_method : " << "a = " << a
<< ", b = " << b
<< ", param_1 = " << param_1
<< ", param_2 = " << param_2 << std::endl;
}
};
int main() {
SwapValues sv;
int c = 3;
int d = 4;
sv.wrong_method(c,d);
sv.right_method(c,d);
return 0;
}
Gives
wrong_method : a = 3, b = 4, this->a = 1, this->b = 2
right_method : a = 1, b = 2, param_1 = 3, param_2 = 4
This should demonstrate what I meant. The right and wrong because the wrong function has a name clash between the parameters and the attributes of the object. It makes errors possible and reflects bad design.
#include <iostream>
using namespace std;
class swap_value
{
private:
int a;
int b;
public:
swap_value()
{
cout<<"enter two numbers to swap";
cout<<"value of a is:";
cin>>a;
cout<<"value of b is:";
cin>>b;
}
void swap()
{
int temp=a;
a=b;
b=temp;
cout<<"value of a is :"<<a;
cout<<"value of b is :"<<b;
}
};
int main() {
swap_value obj;
obj.swap();
return 0;
}

Polymorphism program

I am needing help with polymorphism. I have no clue how to work with this. I have to write a program that creates an Orc and a Human and demonstrates the behavior of the classes. I am just needing some help with setting this program up. I have set up the classes with the information, but how do I get the createCharacter function to work? Would I have characterTotal = characterStrength + characterDexterity + characterIntelligence in the createCharacter function? I know my program is not correct right now and I have some errors and things, but I am still just trying to get a better understanding of this.
UPDATE:
I am having trouble with the createCharacter function. It is a pure virtual function and I am needing some help on how to get it to work.
For Human class createCharacter will:
Get the values of STR, DEX and INT. Will calculate the total of the values.
(Let’s assume STR = 17, DEX = 12 and INT = 10. It will store 37 into characterTotal.Itwill print out a message: “The strong human Paladin, has a total scoreof 37.” (Strong adjective comes due to STR being 17. If something is above 17 you should say something related. STR = strong, DEX = dexterous, INT =
intelligent).
For Orc class createCharacter will:
Get the values of STR, DEX and INT. Will calculate the total of the values.
However Orcs receive -2 to INT and DEX. They receive +2 to STR. (Let’s
assume STR = 16, DEX = 10 and INT = 8. It will store 16+2,10-2,8-2 = 28 into
characterTotal.
It will print out a message “The berserker Orc has a total score of 28.” (Here the
Orcs get their adjectives from their clan names so you do not need to do
something specific to STR, DEX or INT.)
CODE:
//character.h
#ifndef CHARACTER_H
#define CHARACTER_H
using namespace std;
class Character
{
protected:
float characterTotal;
public:
virtual void createCharacter() = 0; //Pure virtual function
};
#endif
//human.h
#ifndef HUMAN_H
#define HUMAN_H
#include "Character.h"
using namespace std;
class Human
{
private:
int characterStrength;
int characterDexterity;
int characterIntelligence;
string characterType;
public:
Human();//Constructor
int getStength
{
cout << "Enter a number from 0 to 18\n";
cin >> characterStrength;
return characterStrength;
}
int getDexterity
{
cout << "Enter a number from 0 to 18\n";
cin >> characterDexterity;
return CharacterDexterity;
}
int getIntelligence
{
cout << "Enter a number from 0 to 18\n";
cin >> characterIntelligence;
return characterIntelligence;
}
string getType
{
cout << "Please choose one of the following\n";
cout << "A -- Paladin \n";
cout << "B -- Ranger \n";
cout << "C -- Wizard \n";\
cin >> characterType;
return characterType;
}
};
#endif
//orc.h
#ifndef ORC_H
#define ORC_H
#include "Character.h"
#include "Human.h"
using namespace std;
class orc
{
private:
int characterStrength;
int characterDexterity;
int characterIntelligence;
string characterClan;
public:
orc(); //Constructor
int getStrength
{
cout << "Enter a number between 0 to 18\n";
cin >> characterStrength;
return characterStrength;
}
int getDexterity
{
cout << "Enter a number between 0 to 18\n";
cin >> characterDexterity;
return characterDexterity;
}
int getIntelligence
{
cout << "Enter a number between 0 to 18\n";
cin >> characterIntelligence;
return characterIntelligence;
}
string getClan
{
cout << "Please choose one of the following\n";
cout << "A -- Barbarian \n";
cout << "B -- Berserker \n";
cout << "C -- Vanguard \n";\
cin >> characterClan;
return characterClan;
}
};
#endif
Example: A class called Account posesses a container with Character. Your classes Human and Orc inherit both from Character. Inside of your Human class you may want to set spell ABC to all characters which are created (in createCharacter). But if the player creates an Orc, you might want to set another spell XYZ to it, instead of ABC. Base classes come in handy here. In this example you see one of these abstract functions in action (Character::initCharacter).
You can put in more abstract functions inside of Character IF the classes which are supposed to inherit from Character MUST / NEED TO implement these functions.
This is only an example. If you want to do it properly, you need more than this and would have to modify all for database access and further abstraction.
enum CharacterType
{
CHAR_INVALID = 0x0,
CHAR_HUMAN = 0x1,
CHAR_ORC = 0x4
};
class Character
{
public:
Character(unsigned int charGUID) //You might want to set data in the constructor already
: m_charGUID(charGUID) //right after it has been load from Account::LoadAccountInformation()
{
std::cout << "Constructor of \"Character\"" << std::endl;
}
virtual ~Character(void) //Cleanup if needed
{
std::cout << "Destructor of \"Character\"" << std::endl;
}
virtual void createCharacter(void) = 0;
virtual void initCharacter(void) = 0;
CharacterType GetTypeID(void)
{ return m_typeID; }
protected:
void SetTypeID(CharacterType ct)
{ m_typeID = ct; }
private:
Character(const Character &);
unsigned int m_charGUID;
CharacterType m_typeID;
};
class Human : public Character
{
public:
Human(unsigned int charGUID)
: Character(charGUID)
{
SetTypeID(CHAR_HUMAN);
std::cout << "Constructor of \"Human\"" << std::endl;
}
virtual ~Human(void) //Cleanup if needed
{
std::cout << "Destructor of \"Human\"" << std::endl;
}
void createCharacter(void) override
{
//Set data...
}
void initCharacter(void) override
{
std::cout << "You initialized a character of type \"Human\"" << std::endl;
}
};
class Orc : public Character
{
public:
Orc(unsigned int charGUID)
: Character(charGUID)
{
SetTypeID(CHAR_ORC);
std::cout << "Constructor of \"Orc\"" << std::endl;
}
virtual ~Orc(void) //Cleanup if needed
{
std::cout << "Destructor of \"Orc\"" << std::endl;
}
void createCharacter(void) override
{
//Set data...
}
void initCharacter(void) override
{
std::cout << "You initialized a character of type \"Orc\"" << std::endl;
}
};
class Account
{
public:
Account(unsigned int accountGUID)
{ m_accGUID = accountGUID; }
//#Return: False if load from database failed
bool LoadAccountInformation(void) //You could give it data also
{
//You could also load data directly from a database here if you'd like to
//Here are just some sample values (partially hardcoded)
characters.clear();
const int charsOnAccount = 1; //Load from database
for (int i = 0; i < charsOnAccount; ++i)
{
CharacterType ct = CHAR_HUMAN; //Load from database
unsigned int characterGUID = i;
switch (ct)
{
case CHAR_HUMAN:
{
characters[characterGUID] = std::move(std::shared_ptr<Character>(new Human(characterGUID)));
} break;
case CHAR_ORC:
{
characters[characterGUID] = std::move(std::shared_ptr<Character>(new Orc(characterGUID)));
} break;
default:
{
std::cout << "Invalid character type: " << ct << std::endl; //Or log to file
} break;
}
}
return true;
}
void InitCharacters(void)
{
for (auto itr = std::begin(characters); itr != std::end(characters); ++itr)
itr->second->initCharacter();
}
private:
//A unique account-GUID
unsigned int m_accGUID;
//Let's say a unique char-GUID and the Character object
std::map<unsigned int, std::shared_ptr<Character> > characters;
//And more information...
};
int main(int argc, char *argv[])
{
Account ac = Account(1);
ac.LoadAccountInformation();
ac.InitCharacters();
return 0;
}

passing primitive data type to a function in c++

I want to implement a function like this
double d = string_to("1223.23",double);
int i = string_to("1223",int);
bool d = string_to("1",bool);
How can I pass the bool, int, double data type to implement this in c++?
Types line int, double and bool can only be passed as template parameters.
You can use templates like this:
#include <string>
#include <sstream>
#include <iostream>
template<typename DataType>
DataType string_to(const std::string& s)
{
DataType d;
std::istringstream(s) >> d; // convert string to DataType
return d;
}
int main()
{
double d = string_to<double>("1223.23");
int i = string_to<int>("1223");
bool b = string_to<bool>("1");
std::cout << "d: " << d << '\n';
std::cout << "i: " << i << '\n';
std::cout << "b: " << b << '\n';
}
As an alternative you can pass your numeric types by reference and rely on function overloading to select the correct function:
void string_to(const std::string& s, double& d)
{
d = std::stod(s);
}
void string_to(const std::string& s, int& i)
{
i = std::stoi(s);
}
void string_to(const std::string& s, bool& b)
{
std::istringstream(s) >> std::boolalpha >> b;
}
int main()
{
double d;
int i;
bool b;
string_to("1223.23", d);
string_to("1223", i);
string_to("true", b);
std::cout << "d: " << d << '\n';
std::cout << "i: " << i << '\n';
std::cout << "b: " << b << '\n';
}
Also you could templatize the second method (an exercise for the reader).
If you really want to do this, you can pass the type by using the typeid operator.
E.g. double d = string_to("1223.23", typeid(double));
Using the library functions atoi, stod would make more sense.
If you're aiming to write more uniform code then you could write a Converter object and use method overloading to get automatic selection by type.
class Converter
{
public:
void fromString(double& value, const char* string);
void fromString(int& value, const char* string);
void fromString(long& value, const char* string);
};
Here's another way that uses tag dispatching. You can compile and run this example.
#include <iostream>
#include <string>
#include <cmath>
namespace detail {
// declare the concept of conversion from a string to something
template<class To>
To string_to(const std::string&);
// make some models of the concept
template<>
int string_to<int>(const std::string& s) {
return atoi(s.c_str());
}
template<>
double string_to<double>(const std::string& s) {
return atof(s.c_str());
}
template<>
std::string string_to<std::string>(const std::string& s) {
return s;
}
// ... add more models here
}
// define the general case of conversion from string with a model tag
// note the unused parameter allows provision of a model that is never used
// thus the model will in all likelihood be optimised away
template<class To>
To string_to(const std::string& from, const To& /* model_tag is unused */)
{
// dispatch to correct conversion function using the To type
// as a dispatch tag type
return detail::string_to<To>(from);
}
using namespace std;
int main()
{
// examples
int a = string_to("100", a);
double b = string_to("99.9", b);
const string s = string_to("Hello", s);
cout << s << " " << a << " " << b << endl;
return 0;
}
output:
Hello 100 99.9