I want to pass function of one object to another function as an argument. Below code is only for indication of the problem, (not realistic code). How can function IdNeeded can take function getNextId of class Bar?
class Foo
{
public:
void IdNeeded(getNextId);
}
class Bar
{
public:
int getNextId()
{
return ++id;
}
private:
int id = 0;
}
int main()
{
Bar bar;
Foo foo;
foo.IdNeeded(bar.getNextId); // foo will get id = 1
Foo anotherFoo;
anotherFoo.IdNeeded(bar.getNextId); // anotherFoo will get id = 2, because "id" is already incremented by one for foo object
}
I tried to use std::function, function pointer, std::bind, but unfortunately could not reach a final solution.
Provide a proper call back definition, and use a lambda to pack your object Foo:
#include <functional>
class Foo
{
public:
void IdNeeded(std::function<int()> f){ f();}
};
class Bar
{
public:
int getNextId()
{
return ++id;
}
private:
int id = 0;
};
int main()
{
Bar bar;
Foo foo;
foo.IdNeeded([&](){return bar.getNextId();}); // foo will get id = 1
}
Related
I've been trying to reference another class inside of a class in C++ and I have no idea how.
I have created a small program to demonstrate the issue
#include <iostream>
class foo{
public:
int variable1 = 012;
};
class bar{
public:
int getFooVariable(){
return variable1; // How would I get bar to refrence foo in foobar?
}
};
class foobar{
public:
bar p1;
foo p2;
};
int main(){
foobar fb;
std::cout << fb.p1.getFooVariable(); << std::endl;
return 0;
}
How would I solve this problem?
You're looking for dependency injection:
class foo
{
public:
int variable1 = 012;
};
class bar
{
foo _foo;
public:
bar(foo& fooInjected) :
_foo(fooInjected)
{}
int getFooVariable() { return _foo.variable1; }
};
There is an idea of inversion of control: bar has no control over the creation of foo instance, which is created outside. It's a common way to inject for instance a service. It's also a very important way to loosely couple classes working together and to mock and to test them. But here foo is a concrete class, instead and ideally you're refering only an interface (c#) or an abstract class (c++) in bar. Which concrete class is behind is out of control of bar. I recommend M. Seeman's book Dependency Injection in .NET to understand this completely.
or inheritance:
class foo
{
public:
int variable1 = 012;
};
class bar: public foo
{
public:
int getFooVariable() { return variable1; }
};
Here, bar builds up heavily on foo. bar is a "richer version" of foo if this makes sense. This is what to choose if there is a high cohesion inside bar.
Invoking a variable through another's instance function is a most horrid idea, that goes against class cohesion:
int getFooVariable(foo* foo) { return foo->variable1; }
Sorry to change the formatting, here's a solution:
#include iostream
class foo
{
public:
int variable1 = 012;
};
class bar
{
public:
int getFooVariable(foo* foo)
{
return foo->variable1; // How would I get bar to refrence foo in foobar?
}
};
class foobar
{
public:
bar p1;
foo p2;
};
int main()
{
foobar fb;
std::cout << fb.p1.getFooVariable(&(fb.p2));
<< std::endl;
return 0;
}
You can add a parameter to the getFooVariable() function to take a foo* reference. The reference can be found when you call the function.
This may have been explored before, but I am not certain how it works out, and how t should in my particular case..
Essentially I have a class, with a callback defined as :
class Foo
{
public:
using someCallbackName = std::function<void(int)>;
void someFunc();
Foo(int, someCallBackName);
private :
someCallbackName m_callBack;
}
void Foo::someFunc()
{
m_callBack(1);
}
I used to call this in main() or by just referencing function of similar signature..
void someOtherFunction(int x)
{
cout << x;
}
int main()
{
Foo::someCallbackName callBack = someOtherFunction;
Foo foo(5, callBack);
}
I decided though, that I may need someOtherFunction as a class member, and put it as part of a class. However, using class member function someOtherFunction as a callback required making it static, which worked fine, but which would mean it wouldn't have access to non-static class members, which sort of defeated the purpose to put it in a class.
I tried using :
C++ callback using class member
and the struct access as given in :
https://en.cppreference.com/w/cpp/utility/functional/bind
..but it does not seem to work, the std::bind to
Foo::someCallbackName callBack = std::bind(not_sure_what_to_use_here);
keeps giving errors saying no suitable conversion, which makes me think that somewhere the signature of callback or mechanism of using std::bind in the code is erroneous.
Keeping class Foo as is, how can m_callBack call someOtherFunction ?
You can "bind" the callback to a non-static member function of a particular object by using labmda:
class X {
public:
void someOtherFunction(int x) const { std::cout << x; }
};
int main()
X x;
Foo::someCallbackName callBack = [&x](int i){ x.someOtherFunction(i); };
Foo foo(5, callBack);
foo.someFunc();
}
Live demo: https://wandbox.org/permlink/fUmrnD6xn1xr7zn0.
To avoid dangling references after x is destroyed, you can employ shared pointers, as follows (note it is captured by value):
Foo::someCallbackName callBack;
{
auto ptr_x = std::make_shared<X>();
callBack = [ptr_x](int i){ ptr_x->someOtherFunction(i); };
}
Foo foo(5, callBack);
foo.someFunc();
Live demo: https://wandbox.org/permlink/23euPcuDUsDENdRe.
As #Daniel Langr said, you can use a lambda function.
Otherwise if you want to use a callback that is a member function you need to bind it to an object.
#include <functional>
#include <iostream>
class Foo
{
public:
using someCallbackName = std::function<void(int)>;
void someFunc();
Foo(int, someCallbackName);
private:
someCallbackName m_callBack;
};
class Bar
{
public:
void someOtherFunction(int x);
};
Foo::Foo(int i, someCallbackName cb)
{
m_callBack = cb;
someFunc();
}
void Foo::someFunc()
{
m_callBack(1);
}
void Bar::someOtherFunction(int x)
{
std::cout << x;
}
int main()
{
Bar bar;
Foo::someCallbackName callBack = std::bind(&Bar::someOtherFunction, &bar, std::placeholders::_1);
Foo foo(5, callBack);
}
Be careful about the lifetime of barwhen doing this.
Oone way to adress the lifetime issue is to make Foo responsible for the lifetime of Bar (this design pattern is called a composition).
#include <functional>
#include <iostream>
// If you declare both class in different files you may need to look into "forward declaration"
class Bar
{
public:
void someOtherFunction(int x);
};
class Foo
{
public:
using someCallbackName = std::function<void(int)>;
void someFunc();
Foo(int, someCallbackName);
private:
someCallbackName m_callBack;
Bar bar;
};
Foo::Foo(int i)
{
m_callBack = std::bind(&Bar::someOtherFunction, &bar, std::placeholders::_1);;
someFunc();
}
// someOtherFunction and someFunc are left unchanged
int main()
{
Foo foo(5);
}
Suppose I have a class Foo which has a member variable of type std::vector<Bar>:
class Foo;
class Bar
{
public:
int x;
Foo* parent;
void trigger(size_t i);
};
class Foo
{
public:
std::vector<Bar> arr;
void moveBack(size_t i);
};
void Bar::trigger(size_t i)
{
parent->moveBack(i);
}
void Foo::moveBack(size_t i)
{
std::swap(arr[i], arr[arr.size()-1]);
}
int main()
{
//...Init foo of type Foo and fill the arr
foo.arr[3].trigger(3);
}
I am wondering if the code above is dangerous or undefined behaviour. Essentially the object of type Bar is moving itself.
Edit: Added forward declaration
class foo{
public:
bar steal_the_moveable_object();
private:
bar moveable_object;
};
main(){
foo f;
auto moved_object= f.steal_the_moveable_object();
}
How can implement steal_the_movebale_object to move the moveable_object into the moved_object ?
You can simply move the member directly in the return statement :
class foo
{
public:
bar steal_the_moveable_object()
{
return std::move(moveable_object);
}
private:
bar moveable_object;
};
Beware that this may not be a good idea though. Consider using the following instead so that the method can only called on R-Values :
class foo
{
public:
bar steal_the_moveable_object() && // add '&&' here
{
return std::move(moveable_object);
}
private:
bar moveable_object;
};
int main()
{
foo f;
//auto x = f.steal_the_moveable_object(); // Compiler error
auto y = std::move(f).steal_the_moveable_object();
return 0;
}
my question is as follows: Suppose I have:
class Foo
{
public:
Foo() {}
void setInt(int i) { myInt = i; }
int getInt() { return myInt; }
private:
int myInt;
};
class Bar
{
public:
Bar(Foo f) { /* do something with f.getInt() */ }
};
Now I have another class that has Bar as a member vairable:
class BarUser
{
public:
BarUser();
private:
Bar bar;
};
I want to write BarUser's constructor, however I want to initialize Bar with a Foo member that has 3 as its integer. I.e.:
Foo f;
f.setInt(3);
Bar b(f);
However since I have Bar as a class member, I cannot write all this code in the initialization list... What I mean is:
BarUser::BarUser() : bar(/* Foo after executing f.setInt(3) */)
{ ... }
Suppose assignment operator is not allowed for Bar - how can I initialize it as intended?
Thanks!
If you can't change Foo, write a function:
Foo make_foo(int i) {
Foo f;
f.setInt(i);
return f;
}
then initialize with bar(make_foo(3)).
You've sort of shot yourself in the foot by giving Foo a constructor but no int constructor. You might be better off adding an explicit constructor to Foo that takes an int.