I have a class that has a function called Update(). I have written several different update methods, so I now have:

class MyClass
{
 double Update1();
 double Update2();
 double Update3();
private:
 float Data1;
...
 float DataN;
};

All of these functions need access to all of the data of MyClass. Is there a better way to specify which one of these functions to use than making a

class MyClass
{
 int UpdateMethod;
};

void MyClass::SetUpdateMethod(int method)
{
 this->UpdateMethod = method;
}

double MyClass::Update()
{
 if(this->UpdateMethod == 1)
   return Update1();
 if(this->UpdateMethod == 2)
   return Update2();
...
}

?

I looked into functors (which are pretty cool: http://programmingexamples.net/index.php?title=CPP/Functor) but unfortunately I can't access the data members of MyClass from a functor.

Any suggestions?

Thanks,

David

Recommended Answers

All 19 Replies

What do these update methods do?

They modify their input value (not shown in the example I posted):

void MyClass::Update(double &a)
{
a += 2.0 * this->Data;
}

David

VernonDozier,

I was trying not to use function pointers. I've always heard "don't use function pointers" haha - I have no actual reason for not wanting to use them.

You didn't really specify, so I'm going to ask. Does each of these "Update" methods have different type/number of arguments or do they all have one (1) double& argument? If so, just rely on the function overloading mechanism.

Fbody,

They all have the same arguments, so overloading is out :(

Okay,

What sort of differences are there in the body of the function(s)? Is there some sort of naming convention you can establish based on the specific differences that is less opaque than Update1(), Update2(), etc.?

Also, as a side note, I find your proposed/example behavior a little strange for a member method. What sort of class is this that you're working on?

EDIT:

...
I looked into functors (which are pretty cool: http://programmingexamples.net/index...le=CPP/Functor) but unfortunately I can't access the data members of MyClass from a functor.
...

You might be able to if you make them friend classes/structs...

You could simply use the Boost.Function and Boost.Bind utilities, as follows:

class MyClass
{
public:
  double Update1();
  double Update2();
  double Update3();
  boost::function< double() > Update;
private:
  float Data1;
 ...
  float DataN;
};

Then, define them as:

class MyClass
{
 int UpdateMethod;
};

void MyClass::SetUpdateMethod(int method)
{
 if(method == 1) 
   this->Update = boost::bind(&MyClass::Update1,this);
 if(method == 2) 
   this->Update = boost::bind(&MyClass::Update2,this);
 if(method == 3) 
   this->Update = boost::bind(&MyClass::Update3,this);
}

Now, MyClass.Update can be called as any other member function.

A slightly more customized version of this would be by using a pointer to the member function and just calling it on this within the Update() function.

commented: Very cool, thanks for the suggestion! +5

@Fbody,

The functions are called:

bool SumProductMessageUpdate(MessageVector& messageVector);
bool MaxProductMessageUpdate(MessageVector& messageVector);
bool MinSumMessageUpdate(MessageVector& messageVector);

and they implement different loops with different equations.

@Mike,

I'm always scared of Boost, but once I figure it out I usually like the result. Here, you have done the figuring out for me, so let me try it :)

Is there a reason you dont want to call the methods directly? If you need to provide the type of method to call it's not as if you need additional context to figure it out.
Just call MyClass::SumProductMessageUpdate () instead of delegating.

Ok, the Boost Function and Bind worked well, thanks!

L7Sqr - True, this doesn't actually help much, you're right. What I was actually hoping for was a way to let people extend my class by providing their own Update() functions in a separate file (i.e. without having to change the MyClass.cxx file directly. That's why I thought the functors were a perfect solution because they could just make a subclass of MyUpdateFunctor and pass it to my class, but the problem is that the update functions need access to MyClass's member data. I guess without some huge design change I'm just out of luck.

Thanks all,

David

Have you considered making a base "functor" class that is a friend of "MyClass"? I don't know how it would work if you have one inherit from that base class, but it's worth a shot.

I would have to pass the functor a pointer to the MyClass that it came from, right?

class FunctorBase
{
 void operator() (MessageVector mv, MyClass* parent)
 {
   cout << parent.Data; // even if Data is private to 'parent', this works if FunctorBase is a friend of MyClass
 }
};

Class MyClass
{
 MyFunctor* functor;
 void SomeFunction()
 {
  functor(MyMessageVector, this);
 }
};

Is that what you meant?

Actually, I was thinking more like this:

class functorBase;

class MyClass {
  friend class functorBase;

 private:
   int someData;

 public:
   void someFunction();
};

class functorBase {
  //...
};

When you make an external class (in this case "functorBase") a friend of another class ("MyClass"), the friend class is allowed access to the private/protected members.

Unfortunately, I really can't offer any more than that in terms of function pointers and stuff. That is a concept that completely escapes me.

But even if the functor class is a nested class of MyClass, it still can't access MyClass's data. See below (particularly the commented line):

#include <iostream>

class Parent
{
  friend class Child;
  int name;
  class Child
  {
    int school;
    void test(Parent* parent) // it is necessary to pass a pointer to the parent when calling this function
    {
      //std::cout << this->name; // this doesn't work - Child doesn't have access to Parent's members
      std::cout << parent->name;
    }
  };
};

int main(int argc, char *argv[])
{
  Parent MyParent;
  
  return 0;
}

Right?

But even if the functor class is a nested class of MyClass, it still can't access MyClass's data. See below (particularly the commented line):

#include <iostream>

class Parent
{
  friend class Child;
  int name;
  class Child
  {
    int school;
    void test(Parent* parent) // it is necessary to pass a pointer to the parent when calling this function
    {
      //std::cout << this->name; // this doesn't work - Child doesn't have access to Parent's members
      std::cout << parent->name;
    }
  };
};

int main(int argc, char *argv[])
{
  Parent MyParent;
  
  return 0;
}

Right?

You're right. It won't be able to access them without an instance, unless they're static members. Is providing an instance a problem for some reason?

commented: Thanks for the discussion! +5

Nope, no problem - just more awkward than I'd like :)

You can provide a way for other developers to access your class' private members - though I would caution against allowing them to do it without using some API.

In either case, here is an example

struct Fun;

class Base {
    int x;
public:
    friend struct Fun;
    Base () : x(0) {}
    int get () { return x; }
    void operate (Fun *);
};

struct Fun {
    void update(Base * base) { base->x = 42; } 
};

void Base::operate (Fun * function) { function->update(this); }

int main () {
    Base b;
    Fun f;
    std::cout << b.get () << std::endl;
    b.operate (&f);
    std::cout << b.get () << std::endl;
    return 0;
}

Which yields

0
42

Maybe something like that will work?

If you want some outside classes to access the private members, there are obvious consequences to that and you should by all means try to find a way in your design in which you can avoid other classes or functions to require access to those private members. However, if all fails and you do have to expose the internals, then there are three options from bad to worst:
1) Use a friend relationship.
2) Create an accessor class (one nested class or friend class that exposes complete access to the internals via a set of accessor/mutator functions).
3) Expose all the internal data (i.e. make everything public). That'S pretty bad.

To help with the friendship of classes, it will get annoying if you have to have a list of friend classes and sort-of require the user to register his new class as a friend. If you can use templates, I suggest something like this:

#include <iostream>

#include <boost/bind.hpp>
#include <boost/function.hpp>

template <typename UpdatePolicy> class MyClass; //forward-declare.

struct InnerUpdatePolicy {
  typedef InnerUpdatePolicy type;
  typedef double result_type;
  typedef double (MyClass<InnerUpdatePolicy>::*update_func)();
  update_func mUpdate;
  InnerUpdatePolicy(update_func aUpdate) : mUpdate(aUpdate) {};
  double operator()(MyClass<InnerUpdatePolicy>* aThis) {
    return (aThis->*mUpdate)();
  };
};

template <typename UpdatePolicy>
class MyClass {
  public:
    friend class UpdatePolicy::type;
    boost::function< double() > Update;
    MyClass(UpdatePolicy aUpdateFunctor) : value(42.0) {
      Update = boost::bind(aUpdateFunctor,this); //bind the this pointer to the functor call.
    };

    //as example, MyClass has one or more default functions for the Update:
    double DefaultUpdate1() {
      return 0.0;
    };
  private:
    double value;
};
//provide a make function too, for convenience: (could return MyClass by pointer too)
template <typename UpdatePolicy>
MyClass<UpdatePolicy> make_MyClass(UpdatePolicy aUpdateFunctor) {
  return MyClass<UpdatePolicy>(aUpdateFunctor);
};

//now, you can do the following other class:
struct OtherClass {
  struct Method1 {
    typedef OtherClass type;
    typedef double result_type;
    OtherClass* mThis;
    Method1(OtherClass* aThis) : mThis(aThis) { };
    double operator()(MyClass<Method1>* aThis) {
      return mThis->UpdateMethod(aThis);
    };
  };
  struct Method2 {
    typedef OtherClass type;
    typedef double result_type;
    double operator()(MyClass<Method2>* aThis) {
      return OtherClass::UpdateStaticFunc(aThis);
    };
  };

  double value;
  OtherClass(double aValue) : value(aValue) { };
  double UpdateMethod(MyClass<Method1>* aThis) {
    return value * aThis->value;
  };
  static double UpdateStaticFunc(MyClass<Method2>* aThis) {
    return 2.0 * aThis->value;
  };
  
};

//Now, the above classes can be used as follows:
int main() {
  MyClass<InnerUpdatePolicy> a = make_MyClass(InnerUpdatePolicy(&MyClass<InnerUpdatePolicy>::DefaultUpdate1));
  std::cout << a.Update() << std::endl;

  OtherClass obj(4.0);
  MyClass<OtherClass::Method1> b = make_MyClass(OtherClass::Method1(&obj));
  std::cout << b.Update() << std::endl;

  MyClass<OtherClass::Method2> c = make_MyClass(OtherClass::Method2());
  std::cout << c.Update() << std::endl;

  return 0;
};

Of course, this fixes the Update function for one instance of MyClass at compile-time, which may or may not be an advantage to you. You can always use a polymorphic base for MyClass to have dynamic binding instead of static.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.