Today I'm working on a singleton test case in c++.
The singleton is working fine but I would like to instantiate the static object when the user try to access a member of it, so if the variable isn't created when we try to access a member of it, it will not crash instead it will simply generate my singleton.
Here's my class.h:
class PDG : public EmployeRH
{
public:
static void Instantiate(std::string nom, std::string prenom);
// Current manual instantiation version of the singleton
PDG* operator->();
// This is the line I just added to overload "->" operator ... But it seems it's never called.
void SePresenter();
static PDG* _instance;
private:
PDG();
~PDG();
PDG(std::string nom, std::string prenom);
int _budget;
};
Methods.cpp
PDG* PDG::_instance=NULL;
PDG::PDG()
{
}
PDG::~PDG()
{
}
PDG::PDG(std::string a_nom, std::string a_prenom):EmployeRH(a_nom,a_prenom)
{
_budget = 100000;
}
void PDG::Instantiate(std::string a_nom, std::string a_prenom)
{
cout << "instantiation pdg" << endl;
if (_instance == NULL)
{
_instance = new PDG(a_nom,a_prenom);
}
}
PDG* PDG::operator->()
{
PDG::Instantiate("Unknown", "Unknown");
return _instance;
}
void PDG::SePresenter()
{
cout << _nom << " " << _prenom << endl;
}
main.cpp
void main()
{
PDG::_instance->SePresenter();
system("pause");
}
The thing is, it goes directly into "SePresenter()" and not into my overloaded operator "->".
If anyone could help it would be greatfull.
Thanks,
Impact
PDG::_instance is a pointer to PDG so -> simply dereferences the pointer and you can't override the behaviour. To override the -> operator you must call it on the class directly not on a pointer: (*PDG::_instance)->SePresenter(). To preserve your desired syntax and to remove the undefined behaviour from dereferencing the null pointer you can change PDG::_instance into a structure which holds your instance pointer.
#include <string>
#include <iostream>
using namespace std;
struct EmployeRH {
EmployeRH() {}
EmployeRH(std::string nom, std::string prenom) {}
std::string _nom;
std::string _prenom;
};
class PDG : public EmployeRH {
public:
static PDG* Instantiate(std::string nom, std::string prenom);
// Current manual instantiation version of the singleton
void SePresenter();
static struct Instance {
PDG* operator->()
{
return PDG::Instantiate("Unknown", "Unknown");
}
} _instance;
private:
PDG();
~PDG();
PDG(std::string nom, std::string prenom);
int _budget;
};
PDG::Instance PDG::_instance;
PDG::PDG()
{
}
PDG::~PDG()
{
}
PDG::PDG(std::string a_nom, std::string a_prenom)
: EmployeRH(a_nom, a_prenom)
{
_budget = 100000;
}
PDG* PDG::Instantiate(std::string a_nom, std::string a_prenom)
{
static PDG instance(a_nom, a_prenom);
cout << "instantiation pdg" << endl;
return &instance;
}
void PDG::SePresenter()
{
cout << _nom << " " << _prenom << endl;
}
int main()
{
PDG::_instance->SePresenter();
return 0;
}
I've also changed your singleton to use a function static which makes your code thread safe.
Related
I need to implement one abstract class, three its concrete subclasses, class which goal to create one of this three classes instances and last class executor of three classes. Requirements are c++98, and not to use if/elseif/else to construct class instance, like i did in a Maker class method make Form. What mechanism i need to avoid if / elseif / else?
For example:
test.h
#ifndef TEST_H
#define TEST_H
#include <iostream>
class Executor {
private:
const std::string name;
public:
Executor(const std::string &name = "") {};
const std::string getname() const {return name;}
};
class BForm {
private:
const std::string _name;
public:
BForm(const std::string &name = "") : _name(name) {};
virtual ~BForm() {};
virtual void execute(const Executor &src) = 0;
const std::string getname() {return _name;}
virtual const std::string gettarget() = 0;
};
class Form1 : public BForm{
private:
std::string _target;
public:
Form1(const std::string &target = "") : BForm("form1"), _target(target) {};
virtual ~Form1() {};
virtual void execute(const Executor &src) {
std::cout << src.getname() << " exec form1 target:" << _target << std::endl;
}
virtual const std::string gettarget() {return _target;}
};
class Form2 : public BForm {
private:
std::string _target;
public:
Form2(const std::string &target = "") : BForm("form2"), _target(target) {};
virtual ~Form2() {};
virtual void execute(const Executor &src) {
std::cout << src.getname() << " exec form2 target:" << _target << std::endl;
};
virtual const std::string gettarget() {return _target;}
};
class Form3 : public BForm {
private:
std::string _target;
public:
Form3(const std::string &target = "") : BForm("form3"), _target(target) {};
virtual ~Form3() {};
virtual void execute(const Executor &src) {
std::cout << src.getname() << " exec form3 target:" << _target << std::endl;
};
virtual const std::string gettarget() {return _target;}
};
class Maker {
public:
BForm *makeForm(const std::string &name, const std::string &target)
{
/* need to avoid */
if (name == "form1")
return new Form1(target);
else if (name == "form2")
return new Form2(target);
else
return new Form3(target);
}
};
#endif
main.cpp
#include "test.h"
int main() {
Maker maker;
BForm *form;
Executor exec("executor");
form = maker.makeForm("form1", "A");
std::cout << form->getname() << " " << form->gettarget() << std::endl;
form->execute(exec);
delete form;
return (0);
}
You could typedef a pointer to function and then use a map from string to this type (pointer to function). And then use your parameter with indexer syntax to access the correct pointer to function.
Here is an example:
#include <iostream>
#include <map>
// The class definitions with a virtual function hello() common to all
class Base { public: virtual void hello() = 0; };
class Derived1 : public Base { public: void hello() { std::cout << "Derived1"; } };
class Derived2 : public Base { public: void hello() { std::cout << "Derived2"; } };
// The object making functions
Base* Maker1() { return new Derived1; }
Base* Maker2() { return new Derived2; }
int main()
{
// In C++98, without auto, it's worthwhile to typedef complicated types.
// The first one is a function type returning a pointer to Base...
typedef Base* MakerT();
// ... the second one is a map type projecting strings to such function pointers
typedef std::map<std::string, MakerT*> StrToMakerT;
/// The actual map projecting strings to maker function pointers
StrToMakerT strToMaker;
// Fill the map
strToMaker["D1"] = &Maker1;
strToMaker["D2"] = &Maker2;
// user input
std::string choice;
// as long as output works, input works, and the user didn't say "Q":
while (std::cout << "Please input 'D1' or 'D2' or 'Q' for quit: "
&& std::cin >> choice
&& choice != "Q")
{
// Prevent adding new entries to the map foir unknown strings
if (strToMaker.find(choice) != strToMaker.end())
{
// Simply look the function up again, the iterator type is too
// cumbersome to write in C++98
Base* b = (*strToMaker[choice])();
b->hello();
std::cout << '\n';
delete b;
}
else
{
std::cout << "Didn't find your choice, try again.\n";
}
}
std::cout << "Thank you, good bye\n";
}
I see the use of a Singleton pointer with online examples, so when I created my own Singleton without a pointer I became very confused as to why every example uses a pointer.
Why is a pointer better than a reference?
Here's my code:
class SimpleSingleton{
private:
static int integerDataMember;
static SimpleSingleton singletonInstance;
SimpleSingleton(){}
public:
static SimpleSingleton GetInstance(){
return singletonInstance;
}
void IncrementDataMember() const { integerDataMember++; }
int GetDataMember() const { return integerDataMember; }
};
SimpleSingleton SimpleSingleton::singletonInstance;
int SimpleSingleton::integerDataMember = 0;
int main()
{
SimpleSingleton::GetInstance().IncrementDataMember();
cout << SimpleSingleton::GetInstance().GetDataMember() << endl;
{
SimpleSingleton::GetInstance().IncrementDataMember();
cout << SimpleSingleton::GetInstance().GetDataMember() << endl;
}
return 0;
}
I'm still learning how the abstract classes work and I want know if I'm on the right track or not.
This is my simplified program :
class CPerson
{
public:
CPerson() = default;
virtual int getMat() = 0;
};
class CStudent : public CPerson
{
public:
CStudent() = default;
CStudent(int MatriculationNr) { this->MatriculationNr = MatriculationNr;}
int getMat() { return MatriculationNr;}
private:
int MatriculationNr;
};
class CTeacher : public CPerson
{
public:
CTeacher() = default;
int getMat(){ return 0;}
private:
std::string name;
};
int main()
{
std::vector<CPerson*> test;
test.push_back(new CStudent(9898));
CTeacher *a = new CTeacher();
return 0;
}
In class CTeacher, I don't have the same private variable like CStudent (MatriculationNr) so I returned 0. The program is working normally. But is what I'm doing here correct or not?
Another question related to the abstract classes : Assuming we use virtual int& getMat() = 0; (with a reference), what should we return in CTeacher class? 0 will not work in this case, right?
Should we initalize a variable with 0 so that we can return it in this function, or is there a better implementation?
Below code sample should answer your question in a rather modern C++ way.
#include <iostream>
#include <string>
#include <vector>
#include <memory>
// I have added a `std::string name` to the CPerson class and
// a `std::string subject` to the CTeachers class
// so both derived classes, CStudent and CTeacher have a name
// of the person involved and each derived class has
// something only it needs, MatrikulationNr for CStudent and
// Subject of teaching for CTeacher in order to deliver a more
// complete and more clearifying answer.
class CPerson {
int dummyMatriculationNr{ 0 };
std::string dummySubject{ "noTeacher" };
protected:
std::string name;
public:
std::string getName() { return name; }
virtual int& getMat() { return dummyMatriculationNr; }
virtual std::string getSubject() { return dummySubject; }
};
class CStudent : public CPerson {
int MatriculationNr{ 0 };
public:
CStudent() = delete; // we dont want anyone using this constructor
explicit CStudent(std::string name, int MatriculationNr) :
MatriculationNr{ MatriculationNr } {
this->name = name;
}
int& getMat() { return MatriculationNr; }
};
class CTeacher : public CPerson {
std::string subject{ "" }; // Subject of teaching
public:
CTeacher() = delete;
explicit CTeacher(std::string name, std::string subject) :
subject{ subject } {
this->name = name;
}
std::string getSubject() { return subject; }
};
int main() {
std::vector<std::unique_ptr<CPerson>> vp;
vp.push_back(std::make_unique<CStudent>("aStudentsName", 8989 ));// or emplace_back
vp.push_back(std::make_unique<CTeacher>("aTeachersName", "mathematics"));
for (auto& e : vp)
std::cout << "Name: " << e->getName() << " MatrNo: " << e->getMat()
<< " TeachingSubject: " << e->getSubject() << std::endl;
}
I hope above sample answers your question. However, using the keyword virtual creates a virtual function table, often called vtable, at runtime which costs performance and is considered not to be high performance computing anymore.
Its also confusing to have a getMat() function available in all derived classes when you need it only in one, the CStudents derived class. Although meaningless in any other class, this function still returns some dummy value there. That can be irritating. Same for the getSubject() function in CTeacher. See the output:
Name: aStudentsName MatrNo: 8989 TeachingSubject: noTeacher
Name: aTeachersName MatrNo: 0 TeachingSubject: mathematics
Consider to solve your question without any keyword virtual and having getMat() and int MatriculationNr in CStudents only and not in the base class at all. I know it is tempting to use virtual but its something to rather avoid as long as possible. For example, MFC, Microsoft Foundation Classes, the maybe biggest class inheritance project ever written, did not use virtual at all!
Consider the following code as an example:
#include <iostream>
#include <string>
#include <vector>
#include <variant>
// a code version without virtual
class CPerson {
protected:
std::string name;
public:
std::string getName() { return name; }
};
class CStudent : public CPerson {
int MatriculationNr{ 0 };
public:
CStudent() = delete; // we dont want anyone using this constructor
explicit CStudent(std::string name, int MatriculationNr) : MatriculationNr{ MatriculationNr } {
this->name = name;
}
int& getMat() { return MatriculationNr; }
};
class CTeacher : public CPerson {
std::string subject{ "" }; // Subject of teaching
public:
CTeacher() = delete;
explicit CTeacher(std::string name, std::string subject) : subject{ subject } {
this->name = name;
}
std::string getSubject() { return subject; }
};
int main() {
std::vector<CStudent> vs; // auto-deleted through RAII
std::vector<CTeacher> vt; // and good for serialisation and or database communication
vs.push_back(CStudent{ "aStudentsName", 9898 });
vt.push_back(CTeacher{ "aTeachersName", "mathematics" });
for (auto s : vs)
std::cout << s.getName() << " " << s.getMat() << std::endl;
for (auto t : vt)
std::cout << t.getName() << " " << t.getSubject() << std::endl << std::endl;
// and here we are done already,
// not listing the two different types in one vector
// but just using a vector for each derived class
//
// but lets try put them now into one vector
// using a more modern way through std::variant
// which keps all data in the vector and not only the
// CPerson part.
std::vector<std::variant<CStudent, CTeacher>> people;
// we could, for example, copy from above vectors
for (auto e : vs)
people.push_back(e);
for (auto e : vt)
people.push_back(e);
// we could insert new ones
people.push_back(CStudent { "aStudentsName1", 9899 });
people.push_back(CTeacher { "aTeachersName1", "physics" });
// and take that vector apart again
std::cout << std::endl << "Output from vector of variant:" << std::endl;
for (auto& e : people)
if (std::holds_alternative<CStudent>(e)) {
CStudent& s = std::get<CStudent>(e);
std::cout << s.getName() << " " << s.getMat() << std::endl;
}
else if (std::holds_alternative<CTeacher>(e)) {
CTeacher& s = std::get<CTeacher>(e);
std::cout << s.getName() << " " << s.getSubject() << std::endl;
}
}
There are numerous ways to achieve the goal to avoid virtual and I hope you did enjoy the above.
Everything in the code above seems alright. Just make sure to delete both objects after using them (the CStudent and the CTeacher).
The first printable(e) is giving "entity" but for the next line, the program crashes. giving some characters. Let me know the error.
#include<iostream>
using namespace std;
class A
{
public:
virtual string getclassname() = 0;
};
class entity : public A
{
public:
string getclassname() override
{
cout << "entity" << endl;
}
};
class player : public entity
{
private:
string m_name2;
public:
player(const string& name2) // Creating a constructor
:m_name2(name2) {}
string getname()
{
return m_name2;
}
public:
string getclassname() override
{
cout << "player" << endl;
}
};
void printable(A* en)
{
cout << en->getclassname() << endl;
}
int main()
{
entity* e = new entity();
player* p = new player("bird");
printable(e);
printable(p);
}
Your getclassname() function doesn't return anything even though it promises it does. This results in undefined behaviour. You should not print, but instead compose a string:
string getclassname() override
{
return "player";
}
Working on a small role-playing game battle system to practice object-oriented code. I have a Party class, which has a vector to store a variable amount of party members.
Initializing my party and adding a member seems to work great. I'm even able to call the member's take_damage() function to change the member's hp and that seems to work too.
But when I check on the same member's hp on the next line using the hp getter, it's right back where it started.
I made a destructor for the member class to see what was going on and according to the output the object is being destroyed many times. Why is this?
class Member
{
private:
int hp;
public:
Member() { hp = 1; }
~Member() { std::cout << "DESTROYED!!" << std::endl; }
int get_hp() { return hp; }
void take_damage(int amt) { hp += amt }
};
class Party {
private:
std::vector<Member> members;
public:
void add_member(Member memb) { members.push_back(memb); }
Member get_member(int num) { return members[num]; }
};
int main() {
Party p;
Member m;
p.add_member(m);
std::cout << p.get_member(0).get_hp() << std::endl;
p.get_member(0).take_damage(4);
std::cout << p.get_member(0).get_hp() << std::endl;
}
Your get_member method returns a copy of the array element, rather than a reference to it. Return a reference, and the member will be modified.
Member& get_member(int num) { return members[num]; }
see small issue in code -=amt
also changed function of get_member
other than that, the code seems fine.
class Member
{
private:
int hp;
public:
Member() { hp = 1; }
~Member() { std::cout << "DESTROYED!!" << std::endl; }
int get_hp() { return hp; }
void take_damage(int amt) { hp -= amt } // This should be -=amt, not +=amt
};
class Party {
private:
std::vector<Member> members;
public:
void add_member(Member memb) { members.push_back(memb); }
Member& get_member(int num) { return members[num]; }
};
int main() {
Party p;
Member m;
p.add_member(m);
std::cout << p.get_member(0).get_hp() << std::endl;
p.get_member(0).take_damage(4);
std::cout << p.get_member(0).get_hp() << std::endl;
}