0

I'm looking at using a factory pattern and spawning threads on instances.

Below is my code, and I get the following error:

error: invalid use of non-static member function ‘virtual void base::threadFunction()’
   75 |   thread t1(myClass1->threadFunction);
#include <memory>
#include <iostream>
#include <thread>

using namespace std;
enum classEnum
{
  class1Enum,
  class2Enum
};

class base
{
  public:
    base(classEnum classType)
    {
      this->classType = classType;
    }

    classEnum getClassEnum() { return classType; }
    virtual void threadFunction() = 0;

  private:
    classEnum classType;
};

class class1: public base
{
  public:
    class1() :
      base(class1Enum)
    {
    }

    void threadFunction()
    {
      cout << "Hello from class1\n";
      //call uniqueFunction using unique variables
    }
  private:
    //unique variable types and functions
};

class class2: public base
{
  public:
    class2() :
      base(class2Enum)
    {
    }

    void threadFunction()
    {
      cout << "Hello from class2\n";
      //call uniqueFunction using unique variables
    }
  private:
    //unique variable types and functions
};

class factory
{
  public:
    static std::shared_ptr<base> create(classEnum classType)
    {
      switch(classType)
      {
        case class1Enum:
          return make_shared<class1>();
        case class2Enum:
          return make_shared<class2>();
        default:
          return NULL;
      }
    }
};

int main()
{
  shared_ptr<base> myClass1 = factory::create(class1Enum);
  shared_ptr<base> myClass2 = factory::create(class2Enum);

  thread t1(myClass1->threadFunction);
  thread t2(myClass2->threadFunction);

  t1.join();
  t2.join();
  return 0;
}

Now, I see that the error says that I am using a non-static method, but changing the base to static means I can no longer access member variables and the derived functions aren't being called (which makes sense).

So how should I spawn these threads?

SailorCire
  • 548
  • 1
  • 7
  • 24
  • @SamVarshavchik the question marked as a duplicate does not take into account that we're dealing with `virtual` functions. It may not be obvious that we need to do `&base::threadFunction` instead of `&class1::threadFunction` or `&class2::threadFunction` here. – Fureeish Nov 03 '21 at 23:35
  • I was able to figure it out using the linked answer, thank you @Fureeish. I need to change my call to: `thread t1(&base::threadFunction, myClass1);` `thread t2(&base::threadFunction, myClass2);` For future people: The reason why it isn't `&myClass1` is because I'm using a `std::shared_ptr` – SailorCire Nov 03 '21 at 23:37
  • 1
    To be a little more pedantic, it's not because you are using `shared_ptr`. It's because you are using a pointer *to the base class*. – Fureeish Nov 03 '21 at 23:39

1 Answers1

1

Since those functions are non-static (i.e., they are called on objects), your threads need objects for them to call. Change this:

thread t1(myClass1->threadFunction);
thread t2(myClass2->threadFunction);

to this:

thread t1(&base::threadFunction, myClass1.get());
thread t2(&base::threadFunction, myClass2.get());

This tells the threads to call threadFunction on the passed objects.

Notice the change in the syntax (& and ::) and that we are calling the base versions - it's because we're passing base*, and virtual will do its thing. We can't force the threads to run any specific implementation (&class1:: or &class2::) because the .get() call could return a base pointer to a type that does not match those specified previously. This information is only available at runtime.

Fureeish
  • 12,533
  • 4
  • 32
  • 62