-1

With a class and a derivative as shown below, is there a way for the base classes methods to return a object reference of the derived type instead of its own type so syntactically i can chain the methods together?

Suppose that object A has methods a1,a2 and derivative AD adds a method ad1 how would one go about making a valid method chain of AD_instance.a1().a2().ad1();?

Below are the two classes in question. Ignoring what it's actually doing, the method chaining is the only important part.

class AsyncWorker() {
pthread_t worker;
public:
  AsyncWorker();
  void *worker_run();
  AsyncWorker& Detach() { /*code*/ return *this;  }
  AsyncWorker& Start()  {
     pthread_create(&worker, NULL, &AsyncWorker::worker_helper, this);
     return *this;
  }
  static void *worker_helper(void *context) {
    return ((AsyncWorker *)context)->worker_run();
  }

};

class workerA : public AsyncWorker {
public: 
  int a;
  workerA(int i) { a = i; }
  void* worker_run() { ++a; sleep(1); }
  workerA& other_method_i_want_to_chain() { return *this };
};

Chained like so.

workerA A(0);
A.Start().Detach().other_method_i_want_to_chain();
Aage Torleif
  • 1,907
  • 1
  • 20
  • 37

2 Answers2

1

You could create a suitable overload in your derived class which dispatches to the base class version but return an object of itself:

class workerA {
    // ...
    workerA& Start() {
        this->AsyncWorker::Start();
        return *this;
    }
    workerA& Detach() {
        this->AsyncWorker::Detach();
        return *this;
    }
    // ...
 };
Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
  • Is there no means to cast the return to a (void *)? My rational is that even if the base class doesn't know about the derived members, the caller's context is the same, correct? I mean, the caller is an instance of the derived class. – Aage Torleif Dec 01 '14 at 05:46
  • The compiler needs to know the static (compile-time) type of an expression to determie which functions are available. When you return a reference to the derived type from the base class function as a reference to the base, the compiler can't know that it is not a derived type. This behavior is different from some other languages, e.g., Smalltalk or Objectionable C[++] where members are looked up at run-time: there is no such ability built into C++. – Dietmar Kühl Dec 01 '14 at 13:45
1

Hope this makes the issue a little clearer for you.

#include <iostream>

struct Base
{
   virtual Base& foo() = 0;
};

struct Derived : Base
{
   virtual Derived& foo()
   {
      std::cout << "Came to Derived::foo()\n";
      return *this;
   }

   void bar()
   {
      std::cout << "Came to Derived::bar()\n";
   }

};

int main()
{
   Derived derived;
   derived.foo().bar(); // OK. From the interface of Derived, foo()
                        // returns a Derived&.
   Base& base = derived;
   base.foo().bar();    // Not OK. From the interface of Base, foo()
                        // returns a Base&.

   return 0;
}
R Sahu
  • 204,454
  • 14
  • 159
  • 270