Whats the correct way of implementing this class?
//Header
#include <boost/shared_ptr.hh>
class MyClass
{
public:
static foo()
static foobar();
private:
class pimpl;
static boost::shared_ptr<pimpl> m_handle;
static bool initialized;
};
//source
namespace
{
bool init()
{
//...
// init() can't access m_handle, unless it is a friend of MyClass
// but that seems a bit "tacky", is there a better way?
}
}
class MyClass::pimpl
{
public:
~pimpl(){}
}
bool MyClass::initialized = init();
MyClass::foo()
{
//...
}
MyClass::foobar()
{
//...
}
MyClass is a singleton -- some call it a glorified global. An oft-abused pattern. Use private ctors and a public static accessor:
MyClass {
public:
static MyClass& Instance() {
static MyClass obj;
return obj;
}
// ...
private:
MyClass() : m_handle(pimpl()), initialized(true) {}
// ...
};
Related
I have c++ library with code following code structure:
#include <vector>
std::vector<Base*> UserClasses;
int main(int argc,char** argv)
{
Init(argc,argv)
while(true)
{
for(auto* class : UserClasses){
class->start();
}
DoStuff();
for(auto* class : UserClasses){
class->update();
}
DoStuff();
}
Shutdown();
}
Base class is interface class with virtual methods.Like this:
class Base
{
public:
Base();
virtual ~Base();
virtual void start() = 0;
virtual void update() = 0;
};
The user will write his own classes like this:
class MyClass : public Base
{
public:
MyClass ();
~MyClass ();
virtual void start() override
{
//userstaff
};
virtual void update() override
{
//userstaff
};
};
I want to allow user to include my library and headers in his project, write his own child classes and compile project into executable.
But how can my library create instance of user classes?
It doesn't know anything about them.
Is it possible somehow create instance of class within header file and push it to vector?
I saw that it can be done by initializing static variables because it happens before main but I don't understand how to implement it.
As properly mentioned in the comments, do not define main in a library. Also, avoid non-const global variables, since this is a bad thing (tm). Instead, define a function and pass UserClasses to it directly. And it is better to encapsulate all the state you have in a class:
class Main {
public:
Main(int argc, char** argv) {
Init(argc, argv);
}
int run(const std::vector<std::unique_ptr<Base>>& user_classes)
{
while(true)
{
for(const auto& class : user_classes){
class->start();
}
DoStuff();
for(const auto& class : user_classes){
class->update();
}
DoStuff();
}
Shutdown();
}
private:
void DoStuff();
void Shutdown();
// ...
};
it can be done by initializing static variables
Yes, here's an example.
This is similar to #fabian's answer, but:
You don't need to manually register the classes.
The classes are not constructed automatically, you do it when you need them.
run on gcc.godbolt.org
#include <cstddef>
#include <iostream>
#include <memory>
#include <vector>
class BaseLow
{
template <typename T> friend class Base;
using factory_func_t = std::unique_ptr<BaseLow>(*)();
static std::vector<factory_func_t> &GetFactoryFuncsMutable()
{
static std::vector<factory_func_t> ret;
return ret;
}
public:
virtual ~BaseLow() {}
virtual void foo() = 0;
static std::vector<factory_func_t> &GetFactoryFuncs()
{
return GetFactoryFuncsMutable();
}
};
template <typename T>
class Base : public BaseLow
{
static std::nullptr_t RegisterSelf()
{
GetFactoryFuncsMutable().push_back([]() -> std::unique_ptr<BaseLow>
{
return std::make_unique<T>();
});
return nullptr;
}
inline static const std::nullptr_t dummy = RegisterSelf();
// Force `dummy` to be instantiated.
static constexpr std::integral_constant<decltype(&dummy), &dummy> dummy_helper{};
};
struct A : Base<A>
{
void foo() override
{
std::cout << "I'm A!\n";
}
};
struct B : Base<B>
{
void foo() override
{
std::cout << "I'm B!\n";
}
};
int main()
{
std::vector<std::unique_ptr<BaseLow>> objects;
for (const auto &func : BaseLow::GetFactoryFuncs())
objects.push_back(func());
for (auto &obj : objects)
obj->foo();
}
But how can my library create instance of user classes?
You can't but you can provide the user with a convenient way of adding a instance. You could e.g. provide a template class that registers an instance of a class in the constructor which allows the user to add an instance by simply defining an instance of this class.
Example
(Static) Library
Base.h
int main(int, char**);
template<typename T>
class BaseRegistrar
{
public:
BaseRegistrar();
};
class Base
{
public:
Base();
virtual ~Base();
virtual void start() = 0;
virtual void update() = 0;
private:
static std::vector<std::unique_ptr<Base>>& GetBaseInstances();
friend int main(int, char**);
template<typename T>
friend class BaseRegistrar;
};
template<typename T>
BaseRegistrar<T>::BaseRegistrar()
{
Base::GetBaseInstances().emplace_back(new T);
}
Base.cpp
#include "Base.h"
Base::Base(){}
Base::~Base(){}
std::vector<std::unique_ptr<Base>>& Base::GetBaseInstances()
{
static std::vector<std::unique_ptr<Base>> instances;
return instances;
}
main.cpp
#include "Base.h"
int main(int argc,char** argv)
{
for(auto& clazz : Base::GetBaseInstances()){
clazz->start();
}
for(auto& clazz : Base::GetBaseInstances()){
clazz->update();
}
}
Executable
MyClass.cpp
#include "Base.h"
#include <iostream>
class MyClass : public Base
{
public:
MyClass ()
{}
~MyClass ()
{}
virtual void start() override
{
std::cout << "MyClass::start()\n";
}
virtual void update() override
{
std::cout << "MyClass::update()\n";
}
};
// adds an instance of the class to the list
BaseRegistrar<MyClass> registrar;
Output
MyClass::start()
MyClass::update()
I have a class MyClass (with several virtual functions) that performs operations on an object called MyType.
The class MyClassImpl inherits MyClass and implements the virtual functions, but I need to add additional members to MyType, but I don't want to modify the class MyType (instead I want to keep it generic).
Now, if I make a MyTypeImpl and inherit MyType, I can add members. But, how do I make the non virtual functions in MyClassImpl (inherited from MyClass) use the new MyTypeImpl?
The only way I can think is to make MyClass use MyTypeImpl but I want to avoid using the implementation in the generic class because I might use various different implementations.
Here is a simple example of what the classes might look like. Of course, the code will not compile because the methods and members added in MyTypeImpl and not MyType.
class MyType {
public:
void increment() {
data_++;
}
protected:
int data_ = 0;
};
class MyClass {
public:
void alg() {
sub_routine_1();
sub_routine_2();
modify_mytype();
};
protected:
MyType mytype_;
virtual void sub_routine_1() = 0;
virtual void sub_routine_2() = 0;
void modify_mytype() {
mytype_.increment();
};
};
class MyTypeImpl : public MyType {
public:
void decrement() {
data_--;
is_decremented = true;
};
protected:
bool is_decremented = false;;
};
class MyClassImpl : public MyClass{
public:
void print() {
mytype_.print();
};
protected:
virtual void sub_routine_1() {
//do algorithm things here
mytype_.increment();
mytype_.increment();
};
virtual void sub_routine_2() {
//do more algorithm things here
mytype_.decrement();
mytype_.decrement();
};
};
After seeing your example I see now that you just want to extend the functionality of that class without modifying the original class. If you need to add additional functions, but you don't want to change the type that is stored in MyClass there isn't any way I know of to make that happen without at least modifying MyType to include virtual functions for the functions you want to call.
You also need to make MyClass take a pointer to MyType so you can use polymorphism and make the calls resolve to the correct implementation:
Dynamic Polymorphism Solution:
#include <iostream>
class MyType {
public:
virtual void increment() {
data_++;
}
// To be implemented by implementation class
virtual void print() = 0;
// To be implemented by implementation class
virtual void decrement() = 0;
protected:
int data_ = 0;
};
class MyTypeImpl : public MyType
{
public:
void print() {
std::cout << 42 << std::endl;
}
void decrement() {
data_--;
is_decremented = true;
};
protected:
bool is_decremented = false;;
};
class MyClass {
public:
MyClass(MyType* mytype)
: mytype_(mytype)
{}
void alg() {
sub_routine_1();
sub_routine_2();
modify_mytype();
};
protected:
MyType* mytype_;
virtual void sub_routine_1() = 0;
virtual void sub_routine_2() = 0;
void modify_mytype() {
mytype_->increment();
};
};
class MyClassImpl : public MyClass{
public:
MyClassImpl(MyType* mytype)
: MyClass(mytype)
{}
void print() {
mytype_->print();
};
protected:
virtual void sub_routine_1() {
//do algorithm things here
mytype_->increment();
mytype_->increment();
};
virtual void sub_routine_2() {
//do more algorithm things here
mytype_->decrement();
mytype_->decrement();
};
};
int main()
{
MyType* mytype = new MyTypeImpl();
MyClass* myclass = new MyClassImpl(mytype);
// Prints "42"
myclass->print();
// Do other stuff with "myclass"
delete myclass;
delete mytype;
}
Note, I am only using a raw pointer in this example for increased clarity. It is highly recommended that you don't use new and delete and use smart pointers to manage the lifetime of your pointers instead.
Static Polymorphism Solution:
Not that the design of this solution is actually any better, but I think this is closer to what you are actually looking for because it doesn't require modifying the MyType class directly. Also the only modification needed for MyClass is to make it a template class:
#include <iostream>
class MyType {
public:
virtual void increment() {
data_++;
}
protected:
int data_ = 0;
};
class MyTypeImpl : public MyType
{
public:
void print() {
std::cout << data_ << std::endl;
}
void decrement() {
data_--;
is_decremented = true;
};
protected:
bool is_decremented = false;
};
template <typename T>
class MyClass {
public:
void alg() {
sub_routine_1();
sub_routine_2();
modify_mytype();
};
protected:
T mytype_;
virtual void sub_routine_1() = 0;
virtual void sub_routine_2() = 0;
void modify_mytype() {
mytype_.increment();
};
};
template <typename T>
class MyClassImpl : public MyClass<T> {
public:
void print() {
this->mytype_.print();
};
protected:
virtual void sub_routine_1() {
//do algorithm things here
this->mytype_.increment();
this->mytype_.increment();
};
virtual void sub_routine_2() {
//do more algorithm things here
this->mytype_.decrement();
this->mytype_.decrement();
};
};
int main()
{
// Use the template to get the correct implementation
MyClassImpl<MyTypeImpl> myclass;
myclass.alg();
myclass.print();
// Do other stuff with my class
}
I have a Singleton class with private Ctor, Dtor and one getInstance() method.
class Single {
public:
virtual void* alloc(size_t size, uint line){}
Single* getInstance() {
if(!m_Instance)
m_Instance = __OSAL_NEW OSAL_Memory;
return m_Instance;
}
private:
Single();
~Single();
static Single* m_Instance;
};
#define Allocate(size_t size)\
(Single::getInstance())->alloc(size, __LINE__)
I need to Mock this class using GMOCK.
Is there any way around to mock it.
You could use factory pattern to create your object.
#include <iostream>
#include <functional>
struct A
{
virtual ~A(){}
virtual void foo() = 0;
};
struct Areal : A
{
virtual void foo(){
std::cout<<"real"<<std::endl;
}
};
struct Amock : A
{
virtual void foo(){
std::cout<<"mock"<<std::endl;
}
};
struct Single
{
typedef std::function< A*() > CreatorFn;
static A* getInstance(){
if ( ! instance() )
instance() = (create())();
return instance();
}
static void setCreator( CreatorFn newFn ){
create() = newFn;
}
private:
static CreatorFn& create(){
static CreatorFn f( [](){return new Areal;} );
return f;
}
static A*& instance(){
static A* p=nullptr;
return p;
}
};
bool useMock = true;
int main()
{
if ( useMock )
{
Single::CreatorFn mockFn( [](){ return new Amock; } );
Single::setCreator( mockFn );
}
Single::getInstance()->foo();
}
You just have to make sure that you set the creator before accessing the instance. Otherwise, a default creator function is going to be invoked.
I'm trying to write a simple class in c++ with getter and setter for a class member variable. The getter works fine, but I cant write the setter. Is it possible to overwrite the "m_var" with a setter or is this only for pointer-variables possible?
class Foo: public QObject {
Q_OBJECT
public:
MyOtherClass& getVar() {
return m_var;
}
private:
MyOtherClass m_var;
};
this should be like that :
// this is your setter
// you can set the var parameter as const because it is just copied to var
void setVar(const MyOtherClass& var){m_var = var;}
//this is your getter
MyOtherClass& getVar() {return m_var;}
// also this getter should be declared as const because you return a copy
// of m_var and thus you do not modify the object
MyOtherClass getVarByCopy() const {return m_var;}
the following code compiles fine with g++ :
class A
{
public :
int someInt;
};
class B{
A m_var;
public:
void setVar(const A& var){m_var = var;}
A& getVar() {return m_var;}
};
int main(int argc, char* argv[])
{
B b;
A a;
a = b.getVar();
b.setVar(a);
return 0;
}
Are we missing something?
class Foo: ...
{
.....
.....
MyOtherClass& getVar() {
return m_var;
}
Your
getVar()
is actually a setter as it returns a non-const reference.
check this code.
class MyOtherClass
{
public:
MyOtherClass(int i=10)
{
m_someInt = i;
}
int m_someInt;
};
class QObject
{
};
class Foo: public QObject
{
// Q_OBJECT
public:
MyOtherClass& getVar()
{
return m_var;
}
private:
MyOtherClass m_var;
};
void someFunc()
{
Foo f1;
printf("%d", f1.getVar().m_someInt);
f1.getVar() = 100;
printf("\r\n %d", f1.getVar().m_someInt);
}
Though i dont like the idea of such design.
If you really want getVar() to only get but not set, then it should be
const MyOtherClass& getVar()const {
return m_var;
}
I have an abstract class:
class A
{
public:
bool loaded_;
virtual int load() = 0;
}
And several derived classes :
class B:public A
{
public:
int load();
static B& instance();
}
class C:public A
{
public:
int load();
static C& instance();
}
The fact is that the code inside ::instance() methods is the same for each class :
static B& B::instance()
{
static B instance_;
if (!instance_.loaded_)
{
instance_.load();
instance_.loaded_=true;
}
return instance_;
}
static C& C::instance()
{
static C instance_;
if (!instance_.loaded_)
{
instance_.load();
instance_.loaded_=true;
}
return instance_;
}
I would like to factorize this ::instance method, but given that it uses the virtual method ::load, i cannot define it in the class A.
Theoretically, i know it's weird since the class A should have 0 instance and B,C should have 1 instance but it also makes sense that this code should be factorized.
How would you solve that problem ?
You could make instance() a free function template:
template<class T>
T& instance()
{
static T instance_;
if (!instance_.loaded_)
{
instance_.load();
instance_.loaded_=true;
}
return instance_;
}
Then you can use it like this:
instance<B>().do_stuff()
This is a common usage of the CRTP, define the function that creates the instance in the template and then instantiate it in each type:
struct A {
virtual ~A() {} // don't forget to make your destructor virtual!
virtual void load() = 0;
};
template <typename T>
struct instance_provider {
static T& instance() { /* implementation */ }
};
struct B : A, instance_provider<B> {
virtual void load();
};
struct C : A, instance_provider<C> {
virtual void load();
};