1

I want to transfer a function pointer in the constructor but get some error Messages...

I my parent class I declared:

class Strip{

public:
     typedef void(Strip::*LOG)(const std::string&);

with a function log(const string&)

In my child class I forward declare Strip with class Strip and have somthing like that

class Observable{

public:

  Observable(const char &signal,Strip::LOG log,const QCustomPlot *plot);

with a parameter

Strip::LOG log;

When I try to compile I get the error's

Strip::LOG has not been declared and LOG in class Strip does not name a type

Any Idea how to fix that?

9
  • 2
    Forward declaring the class only lets you use a pointer to the class itself, not any types declared within. You might need to include the .h into your second file. Commented Feb 2, 2014 at 15:11
  • 1
    typedef void(Strip::*LOG)(const std::string&); is not visible in your child class. Commented Feb 2, 2014 at 15:12
  • 1
    a) use C++ std::function instead of C style function pointers b) when gathering a pointer to member use std::mem_fn to ensure the call can be made correctly. Commented Feb 2, 2014 at 15:24
  • In class Strip: typedef void(*LOG)(const std::string&); some compilers wouldn't like the Strip::*LOG in the class declaration. Commented Feb 2, 2014 at 15:28
  • @KarthikT. Should I include it in there since the parent has already included the header of the child. I once heard that this is not advisable. Or am I to caughtios here Commented Feb 2, 2014 at 16:57

2 Answers 2

1

So passing a pointer to a member function presents several issues:

  1. It's a member function as such it will need to have an instance of the class passed into it to work (the implicit this parameter).
  2. It doesn't prevent the class you're passing it to from knowing about the class the function pointer originates so you gain nothing in terms of hiding.

A better way is to declare an Interface and pass that

// ILogger.hpp
// should be completely virtual
struct ILogger{
    virtual void log(const ::std::string&) = 0;
};

// Strip.cpp
class Strip : public ILogger{
public:
    void log(const ::std::string& data){
        // does something
    }
};


// Observable.cpp
#include "ILogger.hpp"
class Observable{
public:
    Observable(ILogger* logger);
};


// some other file that knows about and constructs both

// has to be a pointer allocated to new to make the Vtables work
::std::unique_ptr<Strip> s(new Strip());

// pass in the pointer to an instance of a class that implements ILogger
Observable observed(s.get());

Using an interface means you can completely abstract the two classes apart and Observable need not know anything about the instance being passed to it other than it implements ILogger. Internally Observable can call the logger by just calling logger->log.

Sign up to request clarification or add additional context in comments.

4 Comments

Ah OK thank you. I keep forgetting the multiple inheritance thing in C++. This would defenetly be the cleanest solution. Thank you for your help
@magu_ because the interface is pure this isn't really multiple inheritance so it avoids almost all of the issues with actual multiple inheritance.
I did forget to mention that Observable will be a Baseclass which will be derived further, plus it is already a derived class. What do you mean with pure, purely virtual. Like an abstract class or an interface in the java sense?
@magu_ I meant pure virtual, so it satisfies the same requirements as an interface in java (you can inherit from multiple interfaces in java, just not multiple classes)
0

May be this code can be usefull (compiled w/o errors):

#include <iostream>
using namespace std;

class Strip{
public:
    typedef void(Strip::*LOG)(const std::string&);
    void log(const string& s)
    {
        cout << "log() called\n";
    }     
};

class Observable{
public:
    Observable( Strip::LOG l )
    {
        Strip s; 
        (s.*l)("string");
    }
};

int main() {
    Strip::LOG log = &Strip::log;
    Observable o( log );
    return 0;
}

http://ideone.com/RD4K1r

2 Comments

Thank you for you answer. As far as I understood you're answer I would need to create an other instance of Strip. The problem is that the function log accesses some properties of Strip (namely Qt gui stuff - but I can't use Qt in Stripe and Observable...). I hand the child a pointer to the parent, but I feel that this would be bad practice. Is there a way to do this without creating a new instance of the class?
@magu_ You can pass Strip instanse to Observable class instead of creation of new Strip object like in my example.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.