What I would like to achieve is the following: I want to allow the users to only create objects of class A if they provide a function - this function may construct and calculate things and set other members of the object. In short, I need a way to only allow a constructor call that includes a function as an argument that is subsequently executed with said constructor call. Imagining it like filling those blanks right now:
void foo()
{
// do something
}
class A
{
public:
A(/*magic*/);
/*
...
*/
A:A()
{
/*magic*/
}
I have read about function pointers but have yet to figure out what this syntax:
int (*const fcnPtr)();
translates into and how I can achieve what I want to achieve with it - assuming this is the "best" way in the first place.
Whatever closes the chain of function definition -> constructor call with link to function -> executing the function during object construction is of interest to me.
Thank you for reading and thank you in advance for any input.
The easiest way to do it is by a template:
class A
{
public:
int i;
template<typename F>
A(F f)
: i(0) /* and other initializers*/
{ f(); } // no need to pass *this, see below
};
// usage:
A a([&]() { a.i = 0; });
Looking at your given example, you can add a function pointer as parameter of the constructor:
void foo()
{
std::cout <<" foo called" << std::endl;
}
void bar()
{
std::cout << "bar called" << std::endl;
}
class A
{
public:
//-----------vvv------->ptr is a pointer to a function that has no parameter and return type void
A(void (*ptr)());
};
A::A(void (*ptr)())
{
//call through ptr
ptr();
}
int main()
{
A a(foo); //this will call foo
A b(bar); //this will cal bar
}
Related
I am learning C++ so maybe my question is dumb. I am creating a function that takes a lambda as a parameter. I just want to know if its safe to call it when the lambda function goes out of scope. With code is easier to explain what I mean:
struct SomeStruct
{
// store pointer to callback function
void (*callback)(bool);
int arg1;
int arg2;
};
void some_method(int arg1, int arg2, void (*on_complete_callback)(bool))
{
SomeStruct s;
s.callback = on_complete_callback;
s.arg1 = arg1;
s.arg2 = arg2;
// this helper class will copy the struct even though it is passed by reference
SomeHelperClass->SomeQueue.enqueue( &s );
// do work on a separate task/thread
SomeHelperClass->CreateThread([](){
// get copy of struct
SomeStruct s_copy;
SomeHelperClass->SomeQueue.dequeue( &s_copy );
// do work that takes time to complete
// IS IT SAFE TO CALL THIS CALLBACK FUNCTION?
s_copy.callback(true);
});
}
So my question is given that code if its safe to have something like this?
void method_1()
{
void (*foo)(bool) = [](bool completedCorrectly)
{
cout << "task completed :" << completedCorrectly << endl;
};
some_method(1,2,foo);
// at this point foo should be deleted no?
// why does this work if foo is executed after method_1 completes and its stack is deleted?
// can I have code like that?
}
Edit 2
Here is the same question with working code instead of pseudo code:
#include <iostream> //for using cout
using namespace std; //for using cout
// 3 pointers
int* _X; // points to integer
int* _Y; // points to integer
void (*_F)(int); // points to function
void print_values()
{
cout << "x=" << *_X << " and y=" << *_Y << endl;
}
void some_function()
{
// create variables that live on stack of some_function
int x = 1;
int y = 2;
void (*foo)(int) = [](int someInt)
{
cout << "value passed to lambda is:" << someInt << endl;
};
// point global variables to variables created on this stack x,y and foo
_X = &x;
_Y = &y;
_F = foo;
// works
_F(11);
// works
print_values();
// when exiting variables x,y and foo should be deleted
}
int main(void)
{
// call some function
some_function();
// DOES NOT WORK (makes sense)
print_values();
// WHY DOES THIS WORK? WHY FOO IS NOT DISTROYED LIKE X AND Y?
_F(10);
return 0;
}
If I where to call that method many times and each time with a different lambda will it work? Will the callback method call the correct lambda every time?
A lambda expression is like a class. It is a blueprint for instantiating objects. Classes exist only in source code. A program actually works with objects created from the blueprint defined by a class. Lambda expressions are a source code blueprint for creating closures. Each lambda expression is transformed into a class by the compiler and instantiated into an object called closure. This class has the ability to capture values (that's that the [] part does) and take parameters (that's that the () part does) for its call operator.
Here is an example:
int main()
{
int i = 42;
auto l = [i](int const x){std::cout << x+i << '\n';};
l(2);
}
The compiler transforms this into something similar to the following (generated with https://cppinsights.io/).
int main()
{
int i = 42;
class __lambda_6_11
{
public:
inline /*constexpr */ void operator()(const int x) const
{
std::operator<<(std::cout.operator<<(x + i), '\n');
}
private:
int i;
public:
__lambda_6_11(int & _i)
: i{_i}
{}
};
__lambda_6_11 l = __lambda_6_11{i};
l.operator()(2);
}
You can see here a class that implements the call operator (operator()) with an int argument. You can also see the constructor taking an argument of type int. And then you can see the instantiation of this class at the end of main and the invocation of its call operator.
I hope this helps you understand better how lambdas work.
Why are we able to call the showA() method without object? But if I use void A::showA(A& x) in the method definition then I have to call it using A's object, why?
#include <iostream>
class A {
public:
int a;
A() { a = 0; }
void showA(A&);
};
void showA(A& x)
{
std::cout << "A::a=" << x.a;
}
int main()
{
A a;
showA(a);
return 0;
}
Why are we able to call the showA() method without object?
You don't call the member function A::showA, but instead the free function showA. In fact, the member function A::showA(A&) is declared, but never defined, only the free function showA(A&) has a definition.
If you want to call A::showA, you need a definition;
void A::showA(A& x) { /* ... */ }
// ^^^ this makes it a member function definition
and then call it as
A a;
a.showA(a);
(Note that it doesn't make much sense to pass the a instance to A::showA invoked on the identical a instance, but that's another issue).
This function
void showA(A& x)
{
std::cout << "A::a=" << x.a;
}
is not a member function of the class A.
It accepts one argument of the type A &.
As for the member function showA then it is declared but not defined.
You could declare it within the class like
class A {
public:
int a;
A() { a = 0; }
void showA() const;
};
and then define it outside the class definition like
void A::showA() const
{
std::cout << "A::a=" << a;
}
In this case the function main can look like
int main()
{
A a;
showA(a);
a.showA();
return 0;
}
You can't call it because showA(the one you are thinking) is not the part of the class.It is a global function.The showA function which you declared in class was never defined. In order to do so modify your code a bit.
Change this piece of code.
void A::showA(const A& x) {
std::cout << "A::a=" << x.a; } // It is advised to make const as it doesn't change state.
I have a simple class X
class X {
public:
template<typename T>
void doSomething(T &completion) {
std::cout << completion(10) << std::endl;
}
};
and a class A and B
class A {
public:
// some code
X* c;
};
class B : public A {
public:
int test(int x) {
return x * x;
}
void execute() {
auto lambda = [] (int x) { cout << x * 50 << endl; return x * 100; };
c->doSomething(lambda); // works
c->doSomething(&B::test); // does not work
}
};
I want to pass to the doSomething method a member method of class B (or any other class derived from A) but it just does not work :/
How can I pass a member function from a derived class as a callback?
Your problem has nothing to do with B being a child class. Your problem is that you're not binding the non-static member function test() to its instance.
You can address this easily, either by using std::bind to return a functor:
c->doSomething(std::bind(&B::test, this, std::placeholders::_1));
and don't forget to #include <functional>,
or use a lambda to wrap the call by putting this in the lambda captures:
c->doSomething([this](int x){ return this->test(x); });
Note: Make sure to change doSomething()'s parameter to be a rvalue reference so it could properly take all this callback goodness in both temporary objects and otherwise. Should look like this:
template<typename T>
void doSomething(T&& completion)
Make B::test a static method and it will work as written:
static int test(int x) {
return x * x;
}
// ...
c->doSomething(&B::test);
This is because a static method doesn't require an implicit instance (a this pointer).
If B::test must be a regular method, then you must pass the instance by using a capturing lambda, like this:
c->doSomething([this] (int x) { return this->test(x); });
NOTE: when getting this code to compile, I needed to change your definition of doSomething to leave the & off of T:
template<typename T>
void doSomething(T completion) {
std::cout << completion(10) << std::endl;
}
This prevents putting a l-value, or non-const, constraint on the function pointer type, which can prevent the compiler from creating a temporary lambda function.
Do you mean c->doSomething([this](int x) { return this->test(x); }); ?
I want to make a class where there is a function that is called automatically, to process information stored within this classes instance.
However each instance has different values and possibly a different way for that content to be handeled.
Therefore I need something simmilar to constructor overloading but in a member function. Where every instance can overload the default function or leave it up to the default to handle the input.
How can that be achieved?
Try to Call Functions in Constructor with if else condition
like:
class abc{
abc(){
if username == "member 1"
functioncall();
else
functioncall();
}
}
As far as I see you need some virtual construction emulation. There is a simple C/C++ way to do it.
// Example program
#include <iostream>
#include <string>
struct A;
typedef void (*cb)(A*);
struct A
{
int m_a;
static void foo(A* aref)
{
std::cout << "Print a: " << aref->m_a << "\n";
}
A(cb b=foo)
{
m_a = 100;
b(this);
}
};
int main()
{
A a;
}
It is not very clear, but still does the trick.
By creating a separate class for the variable behavior Callable describes the local data relating to the function, and by being a class, can be derived.
class Callable {
public:
int m_Value;
Callable(int value) : m_Value(value)
{
}
void operator()( int val1, double val2 /* whatever makes sense */ ) {
}
};
Using the function operator void operator()( ...... ) we create a way of making variables of type Callable to look like a function.
class Variable {
public:
Callable myFunction;
Variable(const Callable & howToCall, /* some more stuff */) :
myFunction(howToCall)
{ /* stuff */
}
void aFunction(int data, double value ) {
myFunction( data, value);
}
};
When calling aFunction the current value of myFunction is called.
Finally Variable can change which function it calls, by modifying the value of myFunction....
myFunction = Callable( /* new parameters */ );
I am trying to send a method of a specific class instance as an argument to a function (foo), although I keep getting this error
invalid use of non-static member function...
(from the line foo(a->bar))
I'm not sure why do I get this error? Is there a possible work-around for it?
#include <iostream>
#include <functional>
void foo(std::function<void(void)> _func)
{
_func();
}
class A
{
public:
A()
{
x = 5;
}
void bar()
{
std::cout << x << std::endl;
}
private:
int x;
};
int main() {
A a;
foo(a->bar);
return 0;
}
You have two options:
Use std::bind: foo(std::bind(&A::bar, a)):
Use lambdas: foo([&a]() { a.bar(); });
Your method isn't compatible to std::function, even it looks like.
Every method has an implicit first argument, this.
So your signature looks like this
void bar(A* this) { /* ... */ }
This is not the case for static methods. These are like functions within the namespace of the class and
static void bar() { /* ... */ }
Will saturate std::function.
Still, using a lambda (c++11) is most likely the better way for ur example.