How to use variables across class files in C++? [duplicate] - c++

This question already has answers here:
How do I use extern to share variables between source files?
(19 answers)
Closed 7 years ago.
I need to use variables I assign in one class into another. For example I have this bit of code. This is CharacterCreation.h followed by CharacterCreation.cpp
#ifndef CHARACTERCREATION_H
#define CHARACTERCREATION_H
class CharacterCreation
{
public:
CharacterCreation();
};
#endif
#ifndef CHARACTERCREATION_H
#define CHARACTERCREATION_H
class CharacterCreation
{
public:
protected:
};
#endif
Here's CharacterCreation.cpp
#include <iostream>
#include "CharacterCreation.h"
#include <string>
CharacterCreation::CharacterCreation()
{
int warrior, mage, rogue, priest;
int class1;
int classID;
std::cout << "Choose a class:\n"
<< "[1] Warrior\n"
<< "[2] Mage\n"
<< "[3] Rogue\n"
<< "[4] Priest\n" << std::endl;
std::cin >> class1;
switch(class1)
{
case 1:
classID=1;
std::cout << "Learned Sword Combat!\n\n";
break;
case 2:
classID=2;
std::cout << "Learned the Arcane Arts!\n\n";
break;
case 3:
classID=3;
std::cout << "Learned the Art of Assasination!\n\n";
break;
case 4:
classID=4;
std::cout << "Learned the Art of the Divine!\n\n";
break;
}
}
And I need to use the class1 variable in main.cpp
#include <iostream>
#include <string>
#include "CharacterCreation.h"
int main()
{
switch(class1)
{
case 1: std::cout << "You chose warrior\n";
case 2: std::cout << "You chose mage\n";
case 3: std::cout << "You chose rogue\n";
case 4: std::cout << "You chose priest\n";
}
}
This code is just an example of what I need, so don't worry about it not working. I just need the method of transferring my variables from CharacterCreation.cpp to main.cpp with them equaling the values I set in CharacterCreation.cpp taught to me.
I'm almost brand new to C++ so if you could ELIF whatever method you teach, that'd be great.

In contrast to the commentors saying there was an "overuse of OOP" - I think that's not the case.
In fact, the code had all the hallmarks of someone new to programming. Case in point:
doing input/output from withing constructors
repetition of code (in general)
repeated switch on "class id" (specificly) <-- this is where the lack of object orientation showed IMO.
Whenever you repeat switch on some kind of type identification, you really want Polymorphic Behaviour. You can model some classes with the different behaviours:
class Character {
public:
virtual std::string name() const = 0;
virtual void acquireSkill() const = 0;
virtual ~Character();
};
class Warrior : public Character {
virtual std::string name() const override;
virtual void acquireSkill() const override;
};
class Mage : public Character {
virtual std::string name() const override;
virtual void acquireSkill() const override;
};
class Rogue : public Character {
virtual std::string name() const override;
virtual void acquireSkill() const override;
};
class Priest : public Character {
virtual std::string name() const override;
virtual void acquireSkill() const override;
};
Now you can just use it as follows:
CharacterCreation factory;
CharacterPtr character = factory.createCharacter(choice);
std::cout << character->name() << "\n";
character->acquireSkill();
The input needs validation. Good input error handling is teh hardz using
C++'s standard library iostreams facilities. See the demo below for some
ideas (which are beyond the scope of my explanations for now though).
The Creation class is likely intended as a kind of factory. So, let's make it so:
using CharacterPtr = std::shared_ptr<Character>;
class CharacterCreation {
public:
enum class Type { none, warrior, mage, rogue, priest };
CharacterPtr createCharacter(Type type);
};
Note that the implementation of createCharacter still does not do the input of the choice!
CharacterPtr CharacterCreation::createCharacter(Type type) {
switch (type) {
case Type::warrior: return std::make_shared<Warrior>();
case Type::mage: return std::make_shared<Mage>();
case Type::rogue: return std::make_shared<Rogue>();
case Type::priest: return std::make_shared<Priest>();
case Type::none: // fall through
break;
}
throw std::range_error("Type"); // character type not implemented?
}
Note: the choice for shared_ptr was a bit arbitrary here. The point is,
for polymorphic object behaviour you need to hold references the the
base-type (implying you typically dynamically allocate the specific
Character subclasses)
Without further ado, the full sample in a single file:
Live On Coliru
#ifndef CHARACTERCREATION_H
#define CHARACTERCREATION_H
#include <memory>
#include <string>
class Character {
public:
virtual std::string name() const = 0;
virtual void acquireSkill() const = 0;
virtual ~Character();
};
class Warrior : public Character {
virtual std::string name() const override;
virtual void acquireSkill() const override;
};
class Mage : public Character {
virtual std::string name() const override;
virtual void acquireSkill() const override;
};
class Rogue : public Character {
virtual std::string name() const override;
virtual void acquireSkill() const override;
};
class Priest : public Character {
virtual std::string name() const override;
virtual void acquireSkill() const override;
};
using CharacterPtr = std::shared_ptr<Character>;
class CharacterCreation {
public:
enum class Type { none, warrior, mage, rogue, priest };
CharacterPtr createCharacter(Type type);
};
#endif
#include <iostream>
//#include "CharacterCreation.hpp"
Character::~Character() { }
CharacterPtr CharacterCreation::createCharacter(Type type) {
switch (type) {
case Type::warrior: return std::make_shared<Warrior>();
case Type::mage: return std::make_shared<Mage>();
case Type::rogue: return std::make_shared<Rogue>();
case Type::priest: return std::make_shared<Priest>();
case Type::none: // fall through
break;
}
throw std::range_error("Type"); // character type not implemented?
}
std::string Warrior::name() const { return "Warrior"; }
std::string Mage::name() const { return "Mage"; }
std::string Rogue::name() const { return "Rogue"; }
std::string Priest::name() const { return "Priest"; }
void Warrior::acquireSkill() const { std::cout << "Learned Sword Combat!\n\n"; }
void Mage::acquireSkill() const { std::cout << "Learned the Arcane Arts!\n\n"; }
void Rogue::acquireSkill() const { std::cout << "Learned the Art of Assasination!\n\n"; }
void Priest::acquireSkill() const { std::cout << "Learned the Art of the Divine!\n\n"; }
//// main.cpp
#include <iostream>
#include <string>
//#include "CharacterCreation.hpp"
namespace {
template <typename T, typename Prompt, typename Validation>
T input(std::istream& is, Prompt prompt, Validation valid)
{
T result;
while (prompt(), !(is >> result) || !valid(result)) {
if (!is && is.eof())
throw std::runtime_error("End of file reading input");
is.clear();
is.ignore(10u << 20, '\n');
}
return result;
}
}
int main() {
auto choice = static_cast<CharacterCreation::Type>(
input<int>(
std::cin,
[] { std::cout << "Choose a character:\n"
<< "[1] Warrior\n"
<< "[2] Mage\n"
<< "[3] Rogue\n"
<< "[4] Priest\n"; },
[](int choice) {
std::cout << "Validation(" << choice << ")\n";
return choice>=1 && choice <=4;
}
)
);
CharacterCreation factory;
CharacterPtr character = factory.createCharacter(choice);
std::cout << character->name() << "\n";
character->acquireSkill();
}
Prints (when inputting '4'):
Choose a character:
[1] Warrior
[2] Mage
[3] Rogue
[4] Priest
Validation(4)
Priest
Learned the Art of the Divine!

CharacterCreation::CharacterCreation()
{
int warrior, mage, rogue, priest;
int class1;
A constructor is very similar to any other kind of function. Just like regular functions, you can declare local variables which are not accessible outside the function. That's what you've done here.
Here's a simplified example of the same problem:
#include <iostream>
void foo() {
int aNumber;
std::cout << "Enter a number! ";
std::cin >> aNumber;
}
int main() {
std::cout << "You entered the number " << aNumber << "\n";
}
Computer programs can be really big and really complex, which makes them really hard to make sure they keep working as new features are added and bugs are fixed. So one of the most critical techniques to avoiding complexity, and to make sure programs are as easy as possible to work on, is to isolate every part of a program as much as possible from other parts of the program, and to tightly control how parts of programs interact with one another.
Languages support this in different ways. One of those ways is the concept of variable scope, or the region of a program that's allowed to interact with a variable. In particular C++ limits the scope of a variable in a function so that nothing outside that function can get at it.
When you do want to have different parts of a program interact, there are many, many ways to do this and it doesn't make much sense to try listing them. Each different method will be suited to different programming goals, so it really depends on what you're doing.
I don't know exactly what your goals are, but having a CharacterCreation class and taking user input in the constructor seems like a dubious design, and it's probably over-complicating things. That said, here's a way to make the program work according to the apparent intent:
// CharacterCreation.h
#ifndef CHARACTERCREATION_H
#define CHARACTERCREATION_H
class CharacterCreation {
int classID;
public:
CharacterCreation();
int getClass();
};
#endif // CHARACTERCREATION_H
// CharacterCreation.cpp
#include "CharacterCreation.h"
#include <cstdlib> // abort()
#include <iostream> // cout, cin, cerr
CharacterCreation::CharacterCreation() {
std::cout << "Choose a class:\n[1] Warrior\n[2] Mage\n"
"[3] Rogue\n[4] Priest\n\n";
std::cin >> classID;
if (std::cin.fail()) {
std::cerr << "Error: failed to get user input.\n";
throw std::runtime_error("input failed");
}
if (classID < 1 || 4 < classID) {
std::cerr << "Error: invalid user input.\n";
throw std::runtime_error("invalid selection");
}
switch (classID) {
case 1:
std::cout << "Learned Sword Combat!\n\n";
break;
case 2:
std::cout << "Learned the Arcane Arts!\n\n";
break;
case 3:
std::cout << "Learned the Art of Assasination!\n\n";
break;
case 4:
std::cout << "Learned the Art of the Divine!\n\n";
break;
default:
abort();
}
}
int CharacterCreation::getClass() { return classID; }
// main.cpp
#include "CharacterCreation.h"
#include <cstdlib> // abort()
#include <iostream> // cout, cin, cerr
int main() {
CharacterCreation cc;
switch (cc.getClass()) {
case 1:
std::cout << "You chose warrior\n";
break;
case 2:
std::cout << "You chose mage\n";
break;
case 3:
std::cout << "You chose rogue\n";
break;
case 4:
std::cout << "You chose priest\n";
break;
default:
abort();
}
}
If I just wanted to write a program with the same output the I might instead write:
// main.cpp
#include <iostream>
#include <array>
struct CharacterClass {
char const *name;
char const *output;
};
int main() {
std::array<CharacterClass, 4> classes = {
{{"Warrior", "Learned Sword Combat!\n\nYou chose warrior"},
{"Mage", "Learned the Arcane Arts!\n\nYou chose mage"},
{"Rogue", "Learned the Art of Assasination!\n\nYou chose rogue"},
{"Priest", "Learned the Art of the Divine!\n\nYou chose priest"}}};
std::cout << "Choose a class:\n";
for (int i = 0; i < classes.size(); ++i) {
std::cout << "[" << i + 1 << "] " << classes[i].name << "\n";
}
int classID;
std::cin >> classID;
if (std::cin.fail()) {
std::cerr << "Error: failed to get user input.\n";
throw std::runtime_error("input failed");
}
if (classID < 1 || classes.size() < classID) {
std::cerr << "Error: invalid user input.\n";
throw std::runtime_error("invalid selection");
}
std::cout << classes[classID - 1].output << '\n';
}

Related

Type of container dynamic array (the size of the array is defined as arguments of the constructor)

The task is to:
Create the abstract class Train nd two derived Passenger/Freight.
Create a container. Type of container dynamic array (the size of the array is defined as arguments of the constructor).
Save the results to the file and delete them from it.
Search in the container and print the train by his number.
I have some questions about where is better to create userInput, storeToArray functions. In the menu file or class as a virtual function or create one more h/cpp?
Why does is the error C2228(VS19) in Menu.cpp/void storeToArray()?
#include"Train.h"
void storeToArray()
{
Train* t;
t = new Train();
t.userInput;
//collection.push_back(t);
}
1>Menu.cpp
1>C:\Users\Admin\source\repos\Menu.cpp(29,3): warning C4002: too many arguments for function-like macro invocation 'assert'
1>C:\Users\Admin\source\repos\Menu.cpp(88,1): warning C4002: too many arguments for function-like macro invocation 'assert'
1>C:\Users\Admin\source\repos\Menu.cpp(105,5): error C2039: 'userInput': is not a member of 'Train'
1>C:\Users\Admin\source\repos\train.h(7): message : see declaration of 'Train'
Does my way of solving this problem is optimal?
How can I make the program better?
https://github.com/brenqP/Course
Menu.h:
#pragma once
#include "PassengerTrain.h"
#include "FreightTrain.h"
#include "train.h"
void greeting();
void showMenu();
void userMenu();
void userInput();
void storeToArray();
//void printInput();
menu.cpp
#include "Menu.h"
#include "file.h"
#include <iostream>
#include <cassert>
void greeting() { std::cout << "Welcome to the Train simulator!\n\n"; }
void showMenu()
{
std::cout<<
"1)Create new train route for the passenger train.\n"<<
"2)Create new train route for the freight train.\n"<<
"3)Save results to the file.\n" <<
"4)Open results from the file.\n" <<
"5)Find train by number.\n"<<
"6)Exit.\n\n";
}
void userMenu()
{
showMenu();
std::cout << "Choose one of the options by printing the number.\n";
int option = 0;
std::cin >> option;
std::cout << "You have chosen the " << option << " option\n";
assert("Invalid input.Please try again later.",option > 0 && option < 7);
//system("cls");
switch (option)
{
case 1:
{//Train:: ;
userInput();
userMenu();
break;
}
case 2:
{
userInput();
userMenu();
break;
}
case 3:
storeToFile();
userMenu();
break;
case 4:
executeFile();
userMenu();
break;
case 5:std::cout << "later";
userMenu();
break;
case 6:
{
std::cout << "\nOkay, see you next time.\n";
std::exit(0);
break;
}
default:
std::cout << "Something went wrong, please try again later\n";
std::exit (0);
}
}
void userInput()
{
std::cout << "Input the number of the train you`re willing to create\n";
int number = 0;
std::cin >> number;
assert(number > 0);
std::cout << "Input the path of the train you`re willing to create\n"
<< "Ex. London-Paris\n";
std::string path{ "N / A - N / A" };
std::cin >> path;
std::cout << "Input the time of the departure\n"
<< "Ex. 23.22\n";
double time_of_departure{ 0 };
std::cin >> time_of_departure;
assert(time_of_departure >= 0 && time_of_departure < 24.0,
"Invalid time of the departure ");
//system("cls");
Train g{ number,path,time_of_departure };
g.print();
}
error
void storeToArray()
{
Train* t;
t = new Train();
t.userInput;
//collection.push_back(t);
}
Train.cpp
#include "train.h"
Train::Train(int number, std::string path, double time_of_departure):
m_number{ number },
m_path{ path },
m_time_of_departure{ time_of_departure }
{
}
Train::~Train()
{
}
//void Train::setPassengerTrain()
//{
//Train:setNumber();
//
//}
void Train::setNumber(int number)
{
m_number = number;
}
void Train::setPath(int path)
{
m_path = path;
}
void Train::setTime_of_departure(int time_of_departure)
{
m_time_of_departure = time_of_departure;
}
void Train::print()
{
std::cout<< "The train number \t" <<
getNumber() << " \t "<<
getPath() << " \tis departed at\t " <<
//bug if there is a /t; print 121314 instead of 1
getTime_of_departure()<<'\n' << std::endl;
}
train.h
#pragma once
#include <string>
#include<iostream>
#include <cassert>
#include <vector>
class Train
{
protected:
int m_number{0};
std::string m_path{"N/A-N/A"};
double m_time_of_departure{0};
public :
//some constructors
Train() = default;
Train(int number, std::string path, double time_of_departure);
//destructor
virtual ~Train();
//void setPassengerTrain();
virtual int getNumber() { return m_number; }
void setNumber(int number);
virtual std::string getPath() { return m_path; }
void setPath(int path);
virtual double getTime_of_departure(){ return m_time_of_departure; }
void setTime_of_departure(int time_of_departure);
void print();
};
PassengerTrain.h
#pragma once
#include "train.h"
class PassengerTrain :public Train
{
int m_number{ 0 };
std::string m_path{ "N/A-N/A" };
double m_time_of_departure{ 0 };
public:
//some constructors
PassengerTrain() = default;
PassengerTrain(int number, std::string path, double time_of_departure);
//destructor
~PassengerTrain();
//void setPassengerTrain();
int getNumber() { return m_number; }
void setNumber(int number);
std::string getPath() { return m_path; }
void setPath(int path);
double getTime_of_departure() { return m_time_of_departure; }
void setTime_of_departure(int time_of_departure);
void print();
};
PassengerTrain.cpp
#include"PassengerTrain.h"
PassengerTrain::PassengerTrain(int number, std::string path, double time_of_departure):
m_number{ number },
m_path{ path },
m_time_of_departure{ time_of_departure }{}
PassengerTrain::~PassengerTrain()
{
}
void PassengerTrain::print()
{
std::cout << "The passenger train number \t" <<
getNumber() << " \t " <<
getPath() << " \tis departed at\t " <<
//bug if there is a /t; print 121314 instead of 1
getTime_of_departure() << '\n' << std::endl;
}
The freightTrain is the same as passengerTrain.
This is maybe not a complete answer (since you did not provide a minimally reproducible example to actually work on) but there are many obvious things to fix. Before even looking at details:
C++ is case sensitive, Train and train are two different things to C++, this also applies to include files Train.h and train.h. You CANNOT mix those: fix.
C++ is very flexible in terms of your text formatting, but in some places white-spaces are mandatory. In particular #include"Train.h" must be #include "Train.h"
Let's look at:
#include"Train.h" // at white space --> #include "Train.h"
void storeToArray()
{
Train* t;
t = new Train();
t.userInput;
//collection.push_back(t);
}
where userInput is not a method or property of Train but a free function defined in Menu.h. Thus, very good practice is to also include #include "Menu.h" (this won't fix any of your problems yet).
Another issue is of course that t is a pointer, not an object. You cannot use the dot operator t., but you have to use the arrow operate t->. But this also does not solve any of your problems yet.
It seems to me what you want to achieve is to ask the user for input, create a new Train object, and store it in a collection. For this you better start by changing the definition of void userInput(); in Menu.h to Train* userInput();
Then in "menu.cpp" you also change it to Train* userInput() { and furthermore you change the last to lines of the userInput function from
Train g{ number,path,time_of_departure };
g.print();
(which actually does accomplish nothing useful) to
Train* train = new Train(number, path, time_of_departure);
train->print();
return train; // <-- this is really important since it return your train to the caller
If you do those changes, you at least can produce trains, and store them in a collection as you wish.

How to execute a class method by string input in C++

I am trying to develop a text adventure in C++ where users can input string commands (ex. "take apple").
Here is a very naive sample of code I came up with:
# include <iostream>
using namespace std;
class fruit{
public:
string actual_name;
fruit(string name){
actual_name = name;
}
take() {
cout << "You take a " << actual_name << "." << endl;
}
};
fruit returnObjectFromName(string name, fruit Fruits[]){
for(int i = 0; i <= 1; i++){ // to be modified in future depending on Fruits[] in main()
if (Fruits[i].actual_name == name)
return Fruits[i];
}
}
int main(){
string verb;
cout << "Enter verb: ";
cin >> verb;
string object;
cout << "Enter object: ";
cin >> object;
fruit apple("apple");
fruit Fruits[] = { apple }; // to be extended in future
// returnObjectFromName(object, Fruits). ??? ()
}
How can I possibly get the fruit method with something similar to the function returnObjectFromName, if this is even possible?
I began the development with Python (independently), and there I can at least use eval(), but as I understand in C++ this is not an option.
I tried also with map, but I didn't manage to make it work with methods.
Thank you all for your answers.
Its not good way to rely on reflection in C++ and i think there is no way to list methods in classes. Maybe you can use function pointers but pointer to instance methods are hell.
I recommend to use polymorphism and good design. If some items might be taken, then use interface like this:
#include <iostream>
using namespace std;
class ITakeable {
public:
virtual bool isTakeable() = 0;
virtual void take() = 0;
virtual void cannotTake() = 0;
};
class fruit : public ITakeable {
public:
string actual_name;
fruit(string name){
actual_name = name;
}
bool isTakeable() {
return true;
}
void take() {
cout << "You take a " << actual_name << "." << endl;
}
void cannotTake() {
cout << "not needed to be implemented";
}
};
class airplane : public ITakeable {
public:
string actual_name;
airplane(string name){
actual_name = name;
}
bool isTakeable() {
return false;
}
void take() {
cout << "not needed to be implemented";
}
void cannotTake() {
cout << "You CANNOT take a " << actual_name << "." << endl;
}
};
int main() {
fruit apple("apple");
if (apple.isTakeable()) {
apple.take();
}
airplane plane("boeing");
if (plane.isTakeable()) {
plane.take();
} else {
plane.cannotTake();
}
// use of interface in general
ITakeable * something = &apple;
if (something->isTakeable()) {
something->take();
}
something = &plane;
if (something->isTakeable()) {
something->take();
} else {
something->cannotTake();
}
return 0;
}
Since fruit is a user defined type, you have to declare your own methods for your type or you inherit from one previously defined.
There are a lot of method for "built-in" string type
that Performs virtually the same job as eval (...) in python.
Also I noticed your function need not be defined independently outside of class fruit.

trying to get different outputs from polymorphic function

Hi StackOverflow community!
I'm expecting different outputs depending on the class of object to be printed but that's not the case.
Medium.h
#include "Datum.h"
#include "Person.h"
class Medium
{
public:
Medium(std::string initTitel);
virtual ~Medium(void);
void ausgabe() const;
bool ausleihen(Person person, Datum ausleihdatum);
void zurueckgeben();
unsigned int getID();
protected:
static unsigned int currentID;
unsigned int ID;
std::string titel;
bool status;
Datum datumAusgeliehen;
Person personAusgeliehen;
};
Medium.cpp
#include "Medium.h"
#include <string>
#include <iostream>
unsigned int Medium::currentID = 1;
Medium::Medium(std::string initTitel): titel(initTitel), status(false)
{
ID = currentID++;
}
Medium::~Medium(void) {}
void Medium::ausgabe() const
{
std::cout << "ID: " << ID << std::endl;
std::cout << "Titel: " << titel << std::endl;
switch (status)
{
case true:
std::cout << "Status : Das Medium ist seit dem "
<< datumAusgeliehen << " an "
<< personAusgeliehen.getName() << " ausgeliehen."
<< std::endl;
break;
case false:
std::cout << "Status: Medium ist zurzeit nicht verliehen." << std::endl;
break;
}
}
The function prints ID, title and status to console.
Now depending on the type of Medium, I would like to print extra information using the function void ausgabe() const.
Example: If the Medium is a book(in german buch = book), information about author should be printed, in addition to other information available in Medium class. i.e, I have got the subclass called Buch which also has an void ausgabe() const function, which should print this extra information in class Buch.
Buch.h
#include "Medium.h"
class Buch: public Medium
{
public:
Buch();
Buch(std::string initTitel, std::string initAutor);
virtual ~Buch();
void ausgabe() const;
private:
std::string autor;
};
Buch.cpp
#include "Buch.h"
Buch::Buch(std::string initTitel, std::string initAutor): Medium(initTitel), autor(initAutor)
{ // TODO Auto-generated constructor stub }
Buch::~Buch() { // TODO Auto-generated destructor stub }
void Buch::ausgabe() const
{
Medium::ausgabe();
std::cout << "Autor: " << autor << std::endl;
}
As far as I have: In the class Buch, while calling the output function ausgabe() the extra information autor will be printed automatically. But for the remaining informations from Medium class, could you help. Thanks for your help :)
Now depending on the type of Medium to be printed, I would like to add
extra information to be printed. E.g. if the Medium is a book,
information about author should be printed too.
So you are looking for dynamic-polymorphism. Then, you need to make void ausgabe()const function to virtual in your base class(Medium), in order to call it polymorphically. And you need to override it in other subclasses(for instance class Buch). In the given code anyways these are not there. In addition to that, you also need virtual destructor at your base class.
Then in your class Buch's ausgabe() should be:
void ausgabe()const override
{
Medium::ausgabe(); // call first base class's ausgabe()
std::cout << "autor :" << autor << std::endl;
}
Then in your main, you can do this: See an example code here
int main ()
{
std::unique_ptr<Medium> some_objects[2];
some_objects[0] = std::make_unique<Medium>("Some Title");
some_objects[1] = std::make_unique<Buch>("Title 2", "user9775960");
for(auto& obj_type: some_objects)
obj_type->ausgabe();
return 0;
}
PS: always try to post English written code in the community, so that everybody can follow.

Call method by string and pass arguments

i search for a way to call a method by its string name.
#include <iostream>
#include <string>
class myClass{
public:
void method1(int run){
std::cout << run << std::endl;
}
void method2(int run){
std::cout << run << std::endl;
}
};
int main(){
myClass mc;
std::string call;
call = "method1";
mc.call(1);
call = "method2";
mc.call(2);
}
But the result, is
‘class Myclass’ has no member named ‘call’
I need response "1" and "2";
EDIT :: Very thank's for your help, i get the next solution (i don't know is good for all cases );
#include <iostream>
#include <string>
class myClass{
public:
void method1(int run){
std::cout << "Loaded method => " << run << std::endl;
}
void method2(int run){
std::cout << "Loaded method => " << run << std::endl;
}
void _loadMethods(int method, int params){
switch(method) {
case 1:
method1(params);
break;
case 2:
method2(params);
break;
default:
break;
}
}
};
int main(){
myClass mc;
std::string method;
method = "method2";
if(method == "method1"){
mc._loadMethods(1, 1);
}
if(method == "method2"){
mc._loadMethods(2, 2);
}
}
Thank's
This is not possible in "raw" C++. But... What you are trying to achieve is some kind of Reflection or Class meta-type information.
You can look at this project: http://www.axelmenzel.de/projects/coding/rttr , use Qt: http://doc.qt.io/qt-5/qmetatype.html#details or google for C++ reflection.

C++ runtime error with shared_ptr and builder pattern

I was studying c++ language with shared pointer and builder pattern.
I have written following code that is not working but I don't understand why it emits run-time error.
Could you tell me why it is not working well and how can I solve this problem to work well?
#include <iostream>
#include <memory>
#include <string>
using namespace std;
class Popup
{
public:
Popup(int value, string str){
this->v = value;
this->str = str;
}
virtual void print() = 0;
int v;
string str;
};
typedef shared_ptr<Popup> PopupPtr;
class PopupA : public Popup
{
public:
PopupA(int v, string str) : Popup(v, str) { }
virtual void print() {
cout << "PopupA" << endl;
}
};
typedef shared_ptr<PopupA> PopupAPtr;
class PopupB : public Popup
{
public:
PopupB(int v, string str) : Popup(v, str) { }
virtual void print() {
cout << "PopupB" << endl;
}
};
typedef shared_ptr<PopupB> PopupBPtr;
class Builder
{
public:
PopupPtr popupPtr;
Builder() { };
shared_ptr<Builder> init(int value, string str) {
shared_ptr<Builder> builder;
switch (value)
{
case 1:
popupPtr = PopupAPtr(new PopupA(value, str));
break;
case 2:
popupPtr = PopupBPtr(new PopupB(value, str));
break;
default:
cout << "default error" << endl;
break;
}
if (popupPtr) {
builder = shared_ptr<Builder>(this);
}
else {
cout << "popup is null" << endl;
}
if (!builder) {
cout << "builder is null" << endl;
}
return builder;
}
PopupPtr build()
{
if (!popupPtr) {
cout << "popup is null" << endl;
}
return PopupPtr(popupPtr);
}
};
typedef shared_ptr<Builder> BuilderPtr;
int main()
{
BuilderPtr builderPtr = BuilderPtr(new Builder());
PopupPtr popupPtr1 = builderPtr->init(1, "111111111111")->build();
popupPtr1->print();
PopupPtr popupPtr2 = builderPtr->init(2, "222222222222")->build();
popupPtr2->print();
return 0;
}
Thanks in advance for your answers and sorry for my poor english. If you don't understand my question please make a comment.
Your problem is this line:
builder = shared_ptr<Builder>(this);
This will not create a copy of the std::shared_ptr already tracking this, nor will it affect the reference count of it. This creates an entirely new shared pointer which will track this independently, causing a double-delete when both of the reference counts hit zero.
Fortunately, the standard library provides a solution to this problem in the form of std::shared_from_this.
First you need to enable this for your class:
class Builder : std::enable_shared_from_this<Builder>
{
//...
};
Then instead of creating a new std::shared_ptr from this, call std::shared_from_this:
builder = std::shared_from_this();