I am trying to do something I thought was simple: calling functions that call functions that call functions (from inherited classes) using a chain of pointers. Is there a better way of accomplishing this? Also, in the spirit of C++11, how would I incorporate smart pointers in this example? This example crashes the application:
Here is the sample code, apologies if it looks a little silly:
Actual output (Crashes!):
almost there...
Desired output:
almost there...
hello from function1
f1.h:
#ifndef FUNCTION_1_H
#define FUNCTION_1_H
//f1.h (header file)
#include <iostream>
struct f1{
int _a;
f1() {}
void function1();
};
#endif
f2.h:
#ifndef FUNCTION_2_H
#define FUNCTION_2_H
//f2.h (header file)
#include "f1.h"
struct f2 : public f1{
int _b;
f1* f1_ptr;
f2() :f1(){}
void function2();
};
#endif
f3.h:
#ifndef FUNCTION_3_H
#define FUNCTION_3_H
#include "f2.h"
struct f3 :public f2{
int _c;
f2* f2_ptr;
f3() : f2(){}
void function3();
};
#endif
CPPs:
f3.cpp:
#include "f3.h"
void f3::function3(){
//do stuff...
//e.g. calculate an int Var3
f2_ptr->function2(/*pass Var3 as argument*/);
}
f2.cpp:
#include "f2.h"
void f2::function2(/*receive Var3*/){
//do stuff with Var3
//e.g. maybe use Var3 to calculate an int Var2
std::cout << "almost there..." << std::endl;
f1_ptr->function1(/*pass Var2 as argument*/);
}
f1.cpp:
#include "f1.h"
void f1::function1(/*receive Var2*/){
//take Var2 and use elsewhere
//or continue linking to other functions
std::cout << "hello from function1" << std::endl;
}
main.cpp:
int main(){
f3* ptr3 = new f3;
ptr3->function3();
//delete ptr3;
std::cin.get();
return 0;
}
The problem is that in the upper classes, the pointers f2* and f1* are not initialized, so when you do f2_ptr->function2(), you are trying to access a member function via an uninitialized pointer, which leads to UB (undefined behaviour). Your code is doing basically this:
#include <iostream>
using namespace std;
struct Base
{
void f(){cout << "In f" << endl;}
};
struct Derived
{
Base* ptr;
};
int main()
{
Derived* foo;
foo->ptr->f(); //cannot use foo->ptr, it is not initialized
}
So you have to make sure that in the constructors of f3 you initialize the f2_ptr and so on. About smart pointers, you can use std::unique_ptr or std::shared_ptr, the syntax is std::unique_ptr<Foo> pointer( new Foo ) (and similarly for std::shared). It is highly recommended to use them, for example, you HAVE TO initialize them (cannot arrived at this problem if you'd have used smart pointers)
Here is a hint for how to write f3.cpp:
#include "f3.h"
// define the constructor here (and just declare it in the header `f3.h`)
f3::f3() : f2()
{
auto f2_ptr = std::make_shared<f2>();
// and all our nightmares are over, f2_ptr is now a valid pointer
// which will automatically release the allocated memory
// when the reference count is zero
}
void f3::function3()
{
//do stuff...
//e.g. calculate an int Var3
f2_ptr->function2(/*pass Var3 as argument*/);
}
And since I started this, here is a full C++11 example (it uses in-class initialization) with chaining and that uses smart pointers, which works and is basically equivalent to yours:
#include <iostream>
#include <memory>
using namespace std;
struct Base
{
void f_base()
{
cout << "In f_base" << endl;
}
};
struct Derived
{
void f_derived()
{
cout << "In f_derived" << endl;
}
std::shared_ptr<Base> ptrBase = make_shared<Base>();
};
struct DerivedDerived
{
std::shared_ptr<Derived> ptrDerived = make_shared<Derived>();
};
int main()
{
DerivedDerived *foo = new DerivedDerived;
foo->ptrDerived->ptrBase->f_base(); // OK now
}
PS: this may help you understand what's going on
When does invoking a member function on a null instance result in undefined behavior?
Related
Can I send an instance to a function not by using the . operator?
For example:
// header file
class A
{
public:
void foo() {std::cout << "Hello" << std::endl;}
};
// main file
A instance = new A;
instance.foo();
// instead do something like this
A::foo(instance);
Can I do something like that?
Yes, you can indirectly via std::invoke:
#include <functional>
#include <iostream>
struct A {
void foo() {
std::cerr << "hi\n";
}
};
int main() {
A a;
std::invoke(&A::foo,a);
}
But std::invoke's implementation will internally probably just apply the .* operator.
You're more than welcome to use the pointer to member syntax.
A instance;
auto fn = &A::foo;
(instance.*fn)();
.* is a different operator than .. Whether this is more readable is left as an exercise to the reader (hint: it's not)
I need help with passing a function pointer on C++. I can't linkage one function for a class to other function. I will explain. Anyway I will put a code resume of my program, it is much larger than the code expose here but for more easier I put only the part I need to it works fine.
I have one class (MainSystem) and inside I have an object pointer to the other class (ComCamera). The last class is a SocketServer, and I want when the socket received any data, it sends to the linkage function to MainSystem.
ComCamera is a resource Shared with more class and I need to associate the functions ComCamera::vRecvData to a MainSystem::vRecvData or other function of other class for the call when receive data and send de data to the function class associate.
Can Anyone help to me?
EDDITED - SOLUTION BELOW
main.cpp
#include <iostream>
#include <thread>
#include <string>
#include <vector>
#include <cmath>
#include <string.h>
#include <stdio.h>
#include <exception>
#include <unistd.h>
using std::string;
class ComCamera {
public:
std::function<void(int, std::string)> vRecvData;
void vLinkRecvFunction(std::function<void(int, std::string)> vCallBack) {
this->vRecvData = vCallBack;
}
void vCallFromCamera() {
this->vRecvData(4, "Example");
};
};
class MainSystem {
private:
ComCamera *xComCamera;
public:
MainSystem(ComCamera *xComCamera) {
this->xComCamera = xComCamera;
this->xComCamera->vLinkRecvFunction([this](int iChannelNumber, std::string sData) {vRecvData(iChannelNumber, sData); });
}
void vRecvData(int iNumber, string sData) {
std::cout << "RECV Data From Camera(" + std::to_string(iNumber) + "): " << sData << std::endl;
};
};
int main(void) {
ComCamera xComCamera;
MainSystem xMainSystem(&xComCamera);
xComCamera.vCallFromCamera();
return 0;
}
Output will be:
MainSystem RECV Data From Camera(4): Example
You can have ComCamera::vRecvData be of type std::function<void(int, std::string)> and then have ComCamera::vLinkRecvFunction() be like this:
void ComCamera::vLinkRecvFunction(std::function<void(int, std::string)> callBack)
{
this->vRecvData = callBack;
}
and have MainSystem constructor be like this:
MainSystem::MainSystem(ComCamera *xComCamera)
{
using namespace std::placeholders;
this->xComCamera = xComCamera;
this->xComCamera->vLinkRecvFunction([this](int iNumber, std::string sData){vRecvData(number, sData);});
}
Still though the original question has way too much code to go through friend.
Here what you want :
#include<iostream>
using std::cout;
class A; //forward declare A
class B{
public:
void (A::*ptr)(int x); //Only declare the pointer because A is not yet defined.
};
class A{
public:
void increase_by(int x){
a+=x;
} // this function will be pointed by B's ptr
int a = 0; // assume some data in a;
B b; // creating B inside of A;
void analyze(int y){
(*this.*(b.ptr))(y);
} // Some function that analyzes the data of A or B; Here this just increments A::a through B's ptr
};
int main(){
A a; // creates A
cout<<a.a<<"\n"; // shows initial value of a
a.b.ptr = &A::increase_by; // defines the ptr that lies inside of b which inturns lies inside a
a.analyze(3); // calls the initialize method
(a.*(a.b.ptr))(3); // directly calls b.ptr to change a.a
cout<<a.a; // shows the value after analyzing
return 0;
}
Output will be :
0
6
I still don't get why would you do something like this. But maybe this is what you wanted as per your comments.
To know more read this wonderful PDF.
What do I declare with the following definition:
void (*bar)(A*){ }; //1
My first thought was that I declare and define function pointer and a function the pointer point to. But it's wrong, because any call to the bar() leads to a segmentation fault:
#include <iostream>
#include <vector>
#include <memory>
struct A{ };
void foo(A*){ std:cout << "foo" << std::endl; }
void (*bar)(){ };
int main(){
bar();
}
Moreover, I can't imbed any statement into the "definition":
void (*bar)(A*){ std::cout << "foo" << std::endl };
yeilds compile-time error.
So, what does the declaration //1 mean?
This statement:
void (*bar)(A*){ };
declares a variable named bar of type void(*)(A*), ie "pointer to function taking pointer to A and returning void", and zero-initializes it. Thus, it's equivalent to this:
void (*bar)(A*) = nullptr;
Obviously, when calling this bar, a segfault should be no surprise.
It's not possible to declare a function and a pointer to that function in a single declaration.
When you say
void (*bar)(A*){ }; //1
it means "bar" is a function pointer which can point to some function which takes "A*" as parameter.
In your case, it is not pointing to any function yet.
to make it working use,
void (*bar)(A*) = foo;
This means you have declared a function pointer that points to nothing at the moment. You should able to validate that using a debugger.
void (*bar)(A*){ }; //1
You could make the pointer point to a function like this:
void foo(A*){ std::cout << "foo" << std::endl };
bar = &foo;
And call it like this now:
A a;
bar(&a);
Full snippet:
#include <iostream>
class A {};
void (*bar)(A*){};
void foo(A*) { std::cout << " foo " << std::endl;}
int main() {
A a;
bar = &foo;
bar(&a);
}
Your code should be changed to the following code.
#include <iostream>
#include <vector>
#include <memory>
struct A{ };
void foo(A*){ std::cout << "foo" << std::endl; }
void (*bar)(A*);
int main(){
A a;
bar = &foo;
bar(&a);
}
To declare an actual function, get rid of the (*) portion around the function name:
void bar(A*){ std::cout << "foo" << std::endl };
https://ideone.com/UPIYxg
So, what does the declaration //1 mean?
It is just a comment.
#include <boost/bind.hpp>
#include <iostream>
using namespace std;
using boost::bind;
class A {
public:
void print(string &s) {
cout << s.c_str() << endl;
}
};
typedef void (*callback)();
class B {
public:
void set_callback(callback cb) {
m_cb = cb;
}
void do_callback() {
m_cb();
}
private:
callback m_cb;
};
void main() {
A a;
B b;
string s("message");
b.set_callback(bind(A::print, &a, s));
b.do_callback();
}
So what I'm trying to do is to have the print method of A stream "message" to cout when b's callback is activated. I'm getting an unexpected number of arguments error from msvc10. I'm sure this is super noob basic and I'm sorry in advance.
replace typedef void (*callback)(); with typedef boost::function<void()> callback;
A bound function doesn't produce an ordinary function, so you cannot just store it in a regular function pointer. However, boost::function is able to handle anything as long as it is callable with the correct signature, so that's what you want. It will work with a function pointer, or a functor created with bind.
After a few corrections to your code, I came up with this:
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <iostream>
// i prefer explicit namespaces, but that's a matter of preference
class A {
public:
// prefer const refs to regular refs unless you need to modify the argument!
void print(const std::string &s) {
// no need for .c_str() here, cout knows how to output a std::string just fine :-)
std::cout << s << std::endl;
}
};
// holds any arity 0 callable "thing" which returns void
typedef boost::function<void()> callback;
class B {
public:
void set_callback(callback cb) {
m_cb = cb;
}
void do_callback() {
m_cb();
}
private:
callback m_cb;
};
void regular_function() {
std::cout << "regular!" << std::endl;
}
// the return type for main is int, never anything else
// however, in c++, you may omit the "return 0;" from main (and only main)
// which will have the same effect as if you had a "return 0;" as the last line
// of main
int main() {
A a;
B b;
std::string s("message");
// you forget the "&" here before A::print!
b.set_callback(boost::bind(&A::print, &a, s));
b.do_callback();
// this will work for regular function pointers too, yay!
b.set_callback(regular_function);
b.do_callback();
}
When using the std::for_each,
class A;
vector<A*> VectorOfAPointers;
std::for_each(VectorOfAPointers.begin(), VectorOfAPointers.end(), std::mem_fun(&A::foo));
If we have classes inheriting from A and implementing foo(), and we hold a vector of pointers to A,
is there any way to call a polymorphic call on foo(), rather then explicitly calling A::foo()?
Note: I can't use boost, only standard STL.
Thanks,
Gal
It actually works this way.
#include <algorithm>
#include <iostream>
#include <functional>
#include <vector>
struct A {
virtual void foo() {
std::cout << "A::foo()" << std::endl;
}
};
struct B: public A {
virtual void foo() {
std::cout << "B::foo()" << std::endl;
}
};
int main()
{
std::vector<A*> VectorOfAPointers;
VectorOfAPointers.push_back(new B());
std::for_each(VectorOfAPointers.begin(), VectorOfAPointers.end(), std::mem_fun(&A::foo));
return 0;
}
prints
B::foo()
So it does exactly what you want. Check that virtual keywords are present though, it's easy to forget them.