I have a weird question. It is so weird it is probably quite easy to solve.
I created a software and I need to implement a class Sing with an sing objeect that must be reached from all classes from the software. Therefore I created it as singleton object in the main function.
My problem is, how can the object sing be reached from other classes (like ClassA) without creating pointers which are handovered by a pointer to every single class in the code.
All the class definition is located in the sing.h file. If I put the definition into the sing.cpp file the compiler will fail.
I managed to create this sing object, but it is not visible from ClassA. How can the object sing be seen without handing over pointers to the constructors of each class?
sing.h file:
#ifndef _SING_H_
#define _SING_H_
//declaration
class Singleton
{
public:
static Singleton* Instance();
static Singleton* InstanceSlave();
int a;
int setTest(int);
protected:
Singleton(){}
private:
static Singleton* _instance;
static Singleton* _instanceSlave;
};
//definitions (only work in header file, not in .cpp file
Singleton* Singleton::_instance =0;
Singleton* Singleton::Instance()
{
if (_instance == 0 )
{
_instance = new Singleton;
}
return _instance;
}
int Singleton::setTest(int b)
{
return 1;
}
#endif _CONF_H_
main.cpp file:
int main()
{
Singleton* sing = sing->Instance();
sing->setTest(2);
ClassA* classa = new ClassA();
}
main.h file:
#inlucde <iostream>
#include "sing.h"
#include "classA.h"
inside the ClassA I would like to have something like this:
classA.h
#inlude sing.h
class classA
{
public:
void doSomeThing(int);
}
classA.cpp:
#include ClassA.h
{
void ClassA::doSomeThing(int a)
{
sing.setTest(a);
}
}
My problem is, how can the object sing be reached from other classes (like ClassA) without creating pointers which are handovered by a pointer to every single class in the code.
The canonical way is to use Scott Meyer's Singleton and provide a static function like
static Singleton& Instance() {
static Singleton theInstance;
return theInstance;
}
Usage is
Singleton::Instance().setTest(2);
In general the Singleton Pattern isn't really considered a good technique, because the coupling with the rest of the code is too tight. It's better to use interfaces (abstract classes) and pass these around as necessary.
Just use
Singleton::Instance()->setTest(a);
Related
I have a struct that multiple classes can access and edit. So I created this struct's object as static in class and created a get method.
In Class1.cpp:
#include "Class1.h"
static MyStruct struct;
MyStruct* Class1::get_my_struct()
{
return &struct;
}
I thought of creating this class`s object as a singleton to guarantee that this struct can be accessed through a single object.
In Class2.cpp:
#include "Class2.h" //Class1.h file included in this file.
void Class2::log_value()
{
Class1& singleton_obj_cls1 = Class1::getObject(): //return singleton object
singleton_obj_cls1 .get_my_struct().tempr_val=log_temp_val(); //log this value of struct by class 2 method
}
void Class2::change_value()
{
Class1& singleton_obj_cls1 = Class1::getObject():
//Do I have to get the singleton object for different methods even though they are in the same class?
//Can a singleton object get in one place in class and the whole class use it as a class member?
singleton_obj_cls1 .get_my_struct().tempr_val=45;
singleton_obj_cls1 .get_my_struct().x_val=66 ;
}
I have class 3 class that uses both class1 and class 2.By the way, I changed class2`constructor to a singleton.
In Class3.cpp:
#include "Class3.h" //Both Class1.h and Class2.h file included in this file.
void Class3::calculate_value()
{
Class1& singleton_obj_cls1 = Class1::getObject():
Class2& singleton_obj_cls2 = Class2::getObject():
singleton_obj_cls2.log_value();
singleton_obj_cls1.get_my_struct().pressure_value=300;
}
My third question is, Is there a better design method that you can fix instead of getting singleton objects in multiple places before using each struct or should I create the object once in the top class and give it as parameters to all 100 methods of perhaps 20 different classes that should have access to this struct?
Do I have to get the singleton object for different methods even though they are in the same class?
Can a singleton object get in one place in class and the whole class use it as a class member?
Use a member variable in your header file and initialize it in the constructor member initializer list:
Example Class2.h
#include "Class1.h"
class Class2 {
//...
private: // maybe public/protected to access from other classes
Class1& m_singleton_obj_cls1;
};
Example Class2.cpp
#include "Class2.h"
Class2::Class2()
: m_singleton_obj_cls1(Class1::getObject()) {
}
//...
In my project I have a class named globalClass which kepts global variables for each classes and their created instances.
The aim of this globalClass to send all other classes and their created instances the same value for its each variable. If one class's instance change that value, the others(including main.cpp) must see the new value.
Think that,
I have a int variable named foo and defined as public and a value of 100 at globalClass.h;
class globalClass
{
public:
int foo = 100;
}
I have a another classes named class2nd,class3rd,class4th
I have intances of class2nd,class3rd and class4th defined like (in main.cpp)
#include "class2nd.h"
#include "class3rd.h"
#include "class4th.h"
class2nd class2ndA;
class2nd class2ndB;
class2nd class2ndC;
class3rd class3rdA;
class3rd class3rdB;
class3rd class3rdC;
class4th class4thA;
class4th class4thB;
class4th class4thC;
I can reach the foo of globalClass from any of the other classes like
(eg. class2nd)
#include "globalClass.h"
globalClass glb;
void globalClass::someFunction()
{
glb.foo = 123;
}
Now I have to see the foo as 123 from all other class but I see it as 100 as defined on globalClass.h. It can only be seen as 123 on class2nd.
What do I have to do to see the foo as unique from all classes and their instances.... ?
One solution would be to use a Singleton for your global class. You can see for example this answer.
The problem here is that you are defining on class per compilation units (ie per .cpp file you compile) which means that would have effectively a different instance of your class in each of your cpp files.
You should also think about using the Singleton Design Pattern as it is rarely a good design to adopt when building an application. You can see this to understand more about its use cases!
As Thomas Caissard told, the solution is Singleton Pattern.
Here is how for anyone who is looking for solution rather than me...
Singleton.h
#ifndef Singleton_H
#define Singleton_H
class Singleton
{
private:
Singleton();
~Singleton();
static bool isInit;
public:
static Singleton* getInstance();
int foo;
};
#endif
Singleton.cpp
#include "Singleton.h"
bool Singleton::isInit=false;
Singleton* Singleton::getInstance()
{
static Singleton s;
return isInit? &s:0;
}
Singleton::Singleton()
{
isInit=true;
}
Singleton::~Singleton()
{
isInit=false;
}
main.cpp( or otherClass with same syntax )
#include "Singleton.h"
void main() {
Singleton* p = Singleton::getInstance();
p->foo = 123; // Use variable from everywhere with same value....
// Other staffs
}
I am trying to implement a singleton design pattern without memory allocation. I tried searching for a solution but it seems like every solution was for a singleton defined with memory allocation.
I made the constructor private and the only code I added to the header file to make this a singleton design pattern was:
static ParametersServerPC& ParametersServerPC::GetInstance() {
static ParametersServerPC instance;
return instance;
}
This is a derived class from the base class ParametersServerABS which has an empty constructor definition. ParametersServerABS is an abstract class.
When I try to instantiate a ParametersServerPC class in a separate file:
ParametersServerPC& paramServer = ParametersServerPC::GetInstance();
I get this error:
undefined reference to `ParametersServerPC::GetInstance()'
Here are the .cpp and .hpp files:
parameters_server_abs.hpp:
#ifndef PARAMETERS_SERVER_ABS_HPP_
#define PARAMETERS_SERVER_ABS_HPP_
class ParametersServerABS {
public:
ParametersServerABS();
~ParametersServerABS();
virtual bool Load() = 0;
};
#endif
parameters_server_abs.cpp:
#include "mid_level/parameters_server_abs.hpp"
ParametersServerABS::ParametersServerABS() {}
ParametersServerABS::~ParametersServerABS() {}
parameters_server_pc.hpp:
#ifndef PARAMETERS_SERVER_PC_HPP_
#define PARAMETERS_SERVER_PC_HPP_
#include <string>
#include "mid_level/parameters_server_abs.hpp"
class ParametersServerPC: public ParametersServerABS {
public:
~ParametersServerPC();
static ParametersServerPC& GetInstance();
virtual bool Load();
private:
ParametersServerPC(std::string parameterFileName = "parameters.txt");
std::string _parameterFileName;
};
parameters_server_pc.cpp:
#include "mid_level/parameters_server_pc.hpp"
ParametersServerPC::ParametersServerPC(std::string parameterFileName = "parameters.txt") :
_parameterFileName(parameterFileName) {
}
ParametersServerPC::~ParametersServerPC() {
}
static ParametersServerPC& ParametersServerPC::GetInstance() {
static ParametersServerPC instance;
return instance;
}
virtual bool ParametersServerPC::Load() {
return true; // TODO
}
my_test_file.cpp
#include "mid_level/parameters_server_pc.hpp"
ParametersServerPC& paramServer = ParametersServerPC::GetInstance();
undefined reference to `ParametersServerPC::GetInstance()'
This seems to be a linker error. If you can post the output of the compilation console we might narrow this down further.
In the meantime you could check your build system and see if you omitted some source files from compilation.
On the singleton pattern there are already some good answers. More on the topic in a description of the pattern and in a general question about singletons.
It is an acceptable pattern. Here is a MVCE demonstrating the feasability :
#include <iostream>
#include <string>
using namespace std;
class A {
public:
int ival;
string strval;
static A& getInstance();
private:
A(int ival, string strval): ival(ival), strval(strval) {}
A(A& src): ival(src.ival), strval(src.strval) {}
~A() {};
};
A& A::getInstance() {
static A instance(1, "foo");
return instance;
}
int main() {
A& a = A::getInstance();
cout << a.ival << endl;
// A a1 = A::getInstance(); error
// A a2 = a; error
// A a3(2, "bar"); error
return 0;
}
First, mark your ~ParametersServerABS(); destructor virtual to be able to delete objects properly. Second, you need to remove virtual and static keywords from parameters_server_pc.cpp file: they are only for definitions (for your header file).
Next, do it right:
class ParametersServerPC {
// your code
private:
ParametersServerPC(std::string parameterFileName = "parameters.txt");
ParametersServerPC(ParametersServerPC const&) = delete;
void operator=(ParametersServerPC const&) = delete;
};
Singleton means that you can't get copies of an object: you need to forbid using of copy constructor and copy assignment operator.
And anyway I think your problem is in static in your parameters_server_pc.cpp file. Remove it from implementation part (cpp file) in order to fix the problem but LEAVE it in the definition part (header file).
If I implement the create method of the class in .cpp I get
error LNK2019: unresolved external symbol "protected: __thiscall Singleton::Singleton(void)" (??0Singleton##IAE#XZ) referenced in function "public: static void __cdecl Singleton::create(void)" (?create#Singleton##SAXXZ
However if I implement the method inside the header file it compiles without any error :S
header file
#pragma once
#include <iostream>
class Singleton
{
public:
static Singleton * getInstance()
{
return s_instance;
}
static void create();
static void destroy();
void help();
protected:
static Singleton * s_instance;
Singleton();
};
source file:
#include "Singleton.h"
Singleton * Singleton::s_instance = NULL;
void Singleton::create()
{
if (!s_instance)
{
s_instance = new Singleton;
}
}
void Singleton::destroy()
{
delete s_instance;
s_instance = NULL;
}
However If I implement the create method inside the header it does not throws any error
Header file with create method implemented in it
#pragma once
#include <iostream>
class Singleton
{
public:
static Singleton * getInstance()
{
return s_instance;
}
static void create(){
if (!s_instance)
{
s_instance = new Singleton;
}
}
static void destroy();
protected:
static Singleton * s_instance;
Singleton();
};
In cpp, your create function is trying to initialize Singleton, by using new operator, but you dont give it an constructor. Try to give an implementation to Singleton(). i.e.:
protected:
static Singleton * s_instance;
Singleton() {}
};
The problem.
You have declared a default constructor, and you're using it (in a new expression), but you haven't implemented it.
Fix.
Simply remove the constructor declaration:
protected:
static Singleton * s_instance;
// Singleton(); -- don't have this. Remove it.
};
Other matters.
With protected features the class is designed for inheritance, so how does one ensure that a derived class can only be instantiated via the singleton machinery?
Well you don't have much control over derived classes, so the easiest is just to document that each derived class should declare and define a non-public default constructor.
However, there is a trick that can be used to enforce this, based on the fact that a virtual base must be initialized by the most derived class. This can be used to force client code to add a final class derivation at bottom. Where that most derived class is a template instantiation, which defines a non-public constructor.
A more practical alternative is to turn things upside-down.
That is, instead of designing the Singleton class for derivation (signalled by protected stuff), design it to inherit from a client code class. Again this means using templates. Andrei Alexandrescu discussed a number of singleton approaches using this idea, in his classic book “Modern C++ Design”.
A C++ n00b question. Is it possible to call a private constructor from a static method defined in the cpp? I'd like to keep methods out of the header file if possible -- I figure there should be a way to do this. I'm getting an error when attempting this:
"cannot access private member declared in class SomeClass"
/////////////////
// SomeClass.h //
/////////////////
class SomeClass {
public:
static SomeClass SomeMethod();
private:
SomeClass(int i);
}
///////////////////
// SomeClass.cpp //
///////////////////
static SomeClass OSImplementation() {
return SomeClass(0);
};
// calls implementation
SomeClass SomeClass::SomeMethod() {
return OSImplementation();
}
You can make OSImplementation a friend method.
Or you can make OSImplementation a static method within the class (but that has to be declared in the header).
Or, probably the most common way to do this, is to have an internal implementation class, like this:
class SomeClass {
public:
//...
private:
struct Impl;
Impl* intern;
};
In your cpp file, you declare struct SomeClass::Impl.
In your constructor, create the SomeClass::Impl instance. Delete it in the destructor. And implement the copy-constructor and the assignment operator!
This is called the PIMPL (pointer to implementation) idiom (Wikipedia, c2.com). It's used a lot in big projects like Qt.
Yes, it is possible, by making the OSImplementation() friend of SomeClass. Next example compiles without warnings and errors using g++ 4.6.1 :
#include <iostream>
// declare in hpp
class SomeClass {
friend SomeClass OSImplementation();
public:
static SomeClass SomeMethod();
void foo();
private:
SomeClass(int);
};
int main()
{
auto obj = SomeClass::SomeMethod();
obj.foo();
}
// define in cpp
SomeClass SomeClass::SomeMethod(){
return SomeClass( 5 );
}
SomeClass::SomeClass(int){
}
void SomeClass::foo(){
std::cout<<"foo"<<std::endl;
}
SomeClass OSImplementation()
{
return SomeClass::SomeMethod();
}