I want to make 'lazy construct' in a C++ class, a simple method to do that is something like this:
#include "b.hpp" // class B
class A {
public:
// invoke B() in b.hpp, this constructor do not actually do init
A(int v_in) : v(v_in) {}
void foo() {
if(flag == false) {
b = create_B_obj();
flag = true;
}
}
private:
B create_B_obj() {
// some expensive ops
//...
}
private:
bool flag = false;
B b;
int v;
};
But a existing problem is that B may not contain a default constructor (B()), so how can I do 'lazy construct' in this case?
BTW: class B in my project is something like a socket which need to do connect or do bind-like calls, so I want to put these expensive ops lazy.
Use pointer, preferably smart pointer.
class A
{
public:
void foo() {
if( pb == nullptr ) {
pb.reset(create_B_obj());
}
}
private:
B* create_B_obj(); //or return std::unique_ptr
private:
std::unique_ptr<B> pb;
int v;
};
You could avoid the dynamic allocation if you use placement-new instead, in which case you need custom deleter with std::unique_ptr:
class A
{
public:
void foo() {
if( pb == nullptr ) {
pb.reset(create_B_obj());
}
}
private:
B* create_B_obj()
{
return new (buffer) B( /* arguments */);
}
private:
std::unique_ptr<B, PlacementNewDeleter> pb;
alignas(B) char buffer[sizeof(B)]; //buffer used by placement new
int v;
};
where PlacementNewDeleter defined as:
struct PlacementNewDeleter
{
template<typename T>
void operator(T const *obj) const { obj->~T(); }
};
Hope that helps.
If you don't have access on the B class, then the easier way to do this is to use a pointer.
std::unique_ptr<B> b;
Then if your foo method:
B foo()
{
if (! b)
b.reset(new B(/* params */));
// or b.reset(create_B_obj());, which should return a pointer (may also return an unique_ptr)
return b;
}
The std::unique_ptr overloads operator bool and manages the memory so you don't have to delete.
Note: I changed the return type of the foo method as it seems more logical like this.
Related
I am trying to add a clone func for class A. This class has a non const and not owned pointer b_. I want to make sure that b_ wont be modified in the cloned objects, but it is ok to modify other member variables, and these non-const func in A can still be called.
A bad way is adding a flag and check it every time before modifying b_. It is bad because if a new func in A is added, some one else might forget to check it.
Is there a better way to achieve this goal?
Here is my bad solution mentioned above:
class A {
public:
A* clone() const {
auto* clone = new A(*this);
clone->is_cloned_ = true;
return clone;
}
void DoSomething() {
if (!is_cloned_){
b_->NonConstFunc();
}
}
void DoSomethingElse() {
other_values = 2; // cloned versions can modify this.
}
private:
is_cloned_ = false;
B* b_; // Not owned
int other_values = 1;
}
You could perhaps design a class hierarchy like this:
class cloned_A;
class A
{
public:
cloned_A *clone ();
private:
B* b_;
};
class cloned_A : public A
{
public:
cloned_A (const B *b) : read_only_b (b) {}
private:
const B* read_only_b;
};
cloned_A *A::clone ()
{
return new cloned_A (b_);
}
Now b_ is private to A and the cloned object can only access read_only_b via a const pointer and therefore cannot modify it.
A way to avoid issue when adding method to A is to wrap the logic to access B in its own class:
class ProtectedB
{
public:
ProtectedB(B& b) : b(&b) {}
ProtectedB(const ProtectedB& rhs) : b(rhs.b), cloned(true) {}
// Duplicate public B interface
void NonConstFunc() {
if (cloned){ return; }
b->NonConstFunc();
}
// Possibly (might avoid to duplicate non mutable interface of B)
const B& GetB() const { return *b; };
private:
B* b = nullptr;
bool cloned = false;
};
Then A is simply:
class A {
public:
// ...
std::unique_ptr<A> clone() const { return std::make_unique<A>(*this); }
void DoSomething() { b.NonConstFunc(); }
void DoSomethingElse() { other_values = 2; } // cloned versions can modify this.
private:
ProtectedB b;
int other_values = 1;
};
Im writing embedded code that cannot use memory allocation!
Also, static objects (therefore constructed before the microcontroller has executed the main funtion with all its initialization) shall be constructed within the main after the initialization, not before.
The only solution people suggest is to use static object pointers and allocate (construct them with new) during initialization. since this is no option for me, is there no other solution?
what i wanna do is as follows:
class A
{
public:
A(int a, bool b)
: myVal1(a), myVal2(b)
{
}
private:
int myVal1;
bool myVal2;
}
class B
{
public:
B(char x)
: myChar1(x) // <-- NO CONSTRUCTION, NO PARAMETER OF MYOBJECTA
{
}
void init()
{
// now i wanna construct myObjectA
myObjectA(123, false);
}
private:
char myChar1;
A myObjectA; // <-- NO CONSTRUCTION, NO PARAMETER
}
static B myObjectB('F'); // <-- NO CONSTRUCTION, NO PARAMETER OF MYOBJECTA
void global_init()
{
// ... do before construction
// now i wanna construct myObjectA
myObjectB.init();
//... do after construction
}
You can use a storage area large enough to create there an instance of A and placement new to control the time you create it.
As an example:
#include
#include
struct A {
A(int a, bool b): myVal1(a), myVal2(b) {}
void foo() {}
private:
int myVal1;
bool myVal2;
};
struct B {
B(char x): myChar1(x) {}
~B() { if(ptr) { ptr->~A(); } }
void init() {
ptr = new (&storage) A{123, false};
}
A * myObjectA() {
return ptr;
}
private:
char myChar1;
std::aligned_storage_t<sizeof(A), alignof(A)> storage;
A *ptr{nullptr};
};
static B myObjectB('F');
void global_init() {
// ... do before construction
// now i wanna construct myObjectA
myObjectB.init();
//... do after construction
}
int main() {
global_init();
myObjectB.myObjectA()->foo();
}
This won't allocate memory (if I got right what you mean for that) and the instance of A is actually created within B::init (that seems to be a requirement from what you wrote in your question).
If you have access to a compiler that supports C++17 or you can use the C++ Boost Libraries, std::optional is a valid alternative as suggested in another answer. Anyway you didn't specify the revision of the standard to which to adhere, so... Here is a way to go in any case.
Do you have boost available?
#include <boost/optional.hpp>
class A
{
public:
A(int a, bool b)
: myVal1(a), myVal2(b)
{
}
private:
int myVal1;
bool myVal2;
};
class B
{
public:
B(char x)
: myChar1(x) // <-- NO CONSTRUCTION, NO PARAMETER OF MYOBJECTA
{
}
A& getA() {
assert(myObjectA);
return myObjectA.get();
}
void init()
{
// now i wanna construct myObjectA
myObjectA.emplace(123, false);
}
private:
char myChar1;
boost::optional<A> myObjectA; // <-- NO CONSTRUCTION, NO PARAMETER
};
static B myObjectB('F'); // <-- NO CONSTRUCTION, NO PARAMETER OF MYOBJECTA
void global_init()
{
// ... do before construction
// now i wanna construct myObjectA
myObjectB.init();
//... do after construction
}
int main()
{
global_init();
}
I am very new to c++ so I am trying to get a feeling of how to do things the right way in c++. I am having a class that uses one of two members. which one gets determined at instantiation. It looks something like
main() {
shared_pointer<A> a = make_shared<A>();
if ( checkSomething ) {
a->setB(make_shared<B>());
} else {
a->setC(make_shared<C>());
}
a->doStuff();
class A {
public:
doStuff() {
/*here I want to do something like call
m_b->doStuff() if this pointer is set and m_c->doStuff() if
that pointer is set.*/
}
setB( B* p ) { m_b = p; }
setC( C* p ) { m_c = p; }
B* m_b;
C* m_c;
}
}
B and C are some classes with doStuff() member function
There are many members like doStuff. Ideally I would avoid checking for nullptr in each of them. What is the best/most efficient/fastest way to create a switch between those two members?
Is there a way to use a static pointer so that I have a member
static **int m_switch;
and do something like
m_switch = condition ? &m_b : &m_c;
and call
*m_switch->doStuff();
Does the compiler here also replace the extra pointer hop because it is a static?
Is there any other smart way to do those switches?
Normally, class A would be an interface class, which both B and C would inherit and implement. But it sounds like you cannot do this for whatever reason.
Since you want to emulate this, you can start by making the interface:
class A_interface
{
public:
virtual void doStuff() = 0;
virtual void doThings() = 0;
virtual void doBeDoBeDo() = 0;
};
And then you make a template wrapper:
template< class T >
class A : public A_interface
{
public:
void doStuff() override { target.doStuff(); }
void doThings() override { target.doThings(); }
void doBeDoBeDo() override { target.doBeDoBeDo(); }
private:
T target;
};
This essentially does half of what your own example class A was trying to do, but now you can use a common interface. All you need to do is construct the correct templated version you want:
std::shared_ptr<A_interface> a;
if( checkSomething ) {
a = std::make_shared<A<B>>();
} else {
a = std::make_shared<A<C>>();
}
a->doStuff();
You need to have both members implement a common interface to use them similarly. But in order to do that, you need to define the interface and relay the calls to the B and C classes.
// existing classes
class B
{
public:
void doStuff() { std::cout << "B"; }
};
class C
{
public:
void doStuff() { std::cout << "C"; }
};
// define your interface
class I
{
public:
virtual void doStuff() = 0;
};
// new classes
class D : public B, public I
{
public:
void doStuff() override { B::doStuff(); }
};
class E : public C, public I
{
public:
void doStuff() override { C::doStuff(); }
};
// your A class
class A
{
public:
D* b = nullptr; // now type D
E* c = nullptr; // now type E
// your toggle
I* getActive()
{
if (b)
return b;
else
return c;
}
// simple doStuff() function
void doStuff()
{
getActive()->doStuff();
}
};
int main()
{
A a;
if (true)
a.b = new D; // need to initialize as D
else
a.c = new E; // need to initialize as E
a.doStuff(); // prints B
}
But typing this up made me realize that defining D and E could get really tiresome and against what you're trying to save. However, you can define a template to create them like #paddy has done.
There's no one-size-fits-all solution for your problem. What to use depends on your particular problem. A few possible answers:
Interfaces
Strategy Pattern
Pointers (to hold a function or class which implements doStuff)
An interface is like a contract. Any class which inherits from the interface must implement its members. For instance,
class IDoesStuff
{
public:
virtual ~IDoesStuff() {};
virtual void DoStuff() = 0;
};
Can now be used by other classes:
class Foo : public IDoesStuff
{
public:
virtual void DoStuff()
{
// ....
}
};
class Bar : public IDoesStuff
{
public:
virtual void DoStuff()
{
// ....
}
};
And now, in general, one may do:
Foo foo;
IDoesStuff *stuffDoer= &foo;
stuffDoer->doStuff();
This can be used in your particular use case as follows:
class A
{
IDoesStuff *stuffDoer; // Initialize this at some point.
public:
void doStuff() { stuffDoer->doStuff(); }
};
First you must change your memebr variables m_b and m_c to std::shared_ptr.
Add a member variable of type std::function(void()) to hold the target function you want to call. In your sample it is do_stuf.
In your setter functions you can bind target function to your std::function and in do_stuf just call std::function.
(You need a C++11 compiler)
class B
{
public:
void doStuff()
{
}
};
class C
{
public:
void doStuff()
{
}
};
class A
{
public:
void doStuff()
{
m_target_function();
}
void setB(std::shared_ptr<B> p)
{
m_b = p;
m_target_function = std::bind(&B::doStuff, m_b.get());
}
void setC(std::shared_ptr<C> p)
{
m_c = p;
m_target_function = std::bind(&C::doStuff, m_c.get());
}
std::shared_ptr<B> m_b;
std::shared_ptr<C> m_c;
std::function<void()> m_target_function;
};
int _tmain(int argc, _TCHAR* argv[])
{
std::shared_ptr<A> a = std::make_shared<A>();
bool use_B = false;
if (use_B)
{
a->setB(std::make_shared<B>());
}
else
{
a->setC(std::make_shared<C>());
}
a->doStuff();
}
I have a struct
struct A {
void f() {}
void g() {}
};
and a custom smart pointer holding a pointer to A:
struct P {
...
A* a;
};
I would like to write P in such a way that that A::f() does not get called when I write
P p;
p->f();
Instead an overloaded function should be called. However, A::g() should still get called when I write
p->g();
I was hoping that I can achieve this by overloading P::operator-> but I didn't succeed. Any suggestions?
Edit: Here is what I tried:
#include <iostream>
struct A {
void f() {}
void g() {}
};
struct P {
struct Wrapper
{
Wrapper(A* aa) : _a(aa) {}
void f()
{
std::cout << "Overloaded\n";
}
A* operator->()
{
return _a;
}
private:
A* _a;
};
Wrapper operator->()
{
return Wrapper(a);
}
private:
A* a;
};
main()
{
P p;
p->f();
}
But this prints nothing at all because when I call p->f(), Wrapper::operator-> gets called instead of Wrapper::f().
Your P::operator-> would generally return an A* raw pointer. To get what you want, you need a proxy object that can be returned instead, which implements those functions.
class A_proxy
{
A* p;
public:
A_proxy(A* ptr) : p(ptr) {}
void f() { /* do whatever crazy stuff you want here */ }
void g() { p->g(); }
};
A_proxy* P::operator->()
{
return &m_proxy;
}
Here's an alternate method based on objections raised in the comments. This one might run into undefined behavior because of the type punning of the pointer though.
struct A_proxy : public A
{
void f() { /* as before, crazy stuff here */ }
};
A_proxy* P::operator->()
{
return static_cast<A_proxy*>(a);
}
class A{
public:
template<typename Obj>
class MyVec{
//some methods...
};
MyVec<A> a; //-> doesnt work
//vector<A> a; //using stl vector-> this works
};
class B{
public:
void someMethod();
private:
A::MyVec<A> b;
};
In the method, when I do sth like:
void someMethod(){
//...
b[0].a.pushback(element);
//...
}
In class A if i use std::vector everything works properly. But when i use nested class it doesn't work.
I've taken your code and modified it as minimally as possible to get something that compiles. This seems to work fine. And so the error is not in the code you have shown us.
#include <iostream>
#include <string>
class A
{
public:
template<typename Obj>
class MyVec{
public:
//My pushback just stores the value away for later.
void pushback(Obj & o )
{
if( obj )
{
*obj = o;
}
else
{
obj = new Obj(o);
}
std::cout<<this<<" : Pushing object "<<&o<<std::endl;
}
//some methods...
//My operator[] just returns the stored object.
Obj& operator[](int i) { return *obj; }
Obj * obj;
MyVec() : obj( NULL ) {}
};
MyVec<A> a;
};
class B
{
public:
B()
{
A an_a;
b.pushback(an_a); //Better store one away since we access it in someMethod.
}
void someMethod()
{
//...
A element;
b[0].a.pushback(element);
//...
}
private:
A::MyVec<A> b;
};
int main()
{
//Test that it all works
B outer;
outer.someMethod();
}
When I run this I get:
0xbffffa5c : Pushing object 0xbffffa0c
0x3ec3c0 : Pushing object 0xbffffa2c
Which is what I'd expect. (one push in the constructor of B and one push to the internal object from someThing)
You can view the result here:
http://ideone.com/BX8ZQ
You really should show the code inside MyVec. As a first guess, maybe MyVec's operator[] isn't returning a reference, so when you do b[0].pushback you're changing a copy instead of what you want; you wouldn't get that problem if you just tested with b.pushback()...