views:

148

answers:

5

Is it possible to return a class through it's own function, so you can chain functions like below:

class Foo;
Foo.setX(12).setY(90);

Can anyone confirm if this is possible, and how it would be achieved?

+4  A: 

Yes its possible. A comon example is operator overloading, such as operator+=().

For example, if you have a class called ComplexNumber, and want to do something such as a+=b, then you could

ComplexNumber& operator+=(ComplexNumber& other){
     //add here
     return *this; 
}

In your case you could use.

Foo& setX(int x){
//yada yada yada
return *this;
}
Tom
You _really_ don't want to do this for `operator+` - that would modify the left-hand argument in expressions like `a = b + c`. This is _not_ what one would expect :)
bdonlan
This should be done for all assignment operator overloads.
Matt Brunell
@bdnolan: Changed to +=
Tom
+10  A: 

For that specific syntax you'd have to return a reference

class Foo {
public:

  Foo& SetX(int x) {
    /* whatever */
    return *this;
  } 

  Foo& SetY(int y) {
    /* whatever */
    return *this;
  } 
};

P.S. Or you can return a copy (Foo instead of Foo&). There's no way to say what you need without more details, but judging by the function name (Set...) you used in your example you probably need a reference return type.

AndreyT
+2  A: 

Well, you can return an object from its own function in order to chain functions together:

#include <iostream>
class foo
{
    public:
        foo() {num = 0;}
        // Returning a `foo` creates a new copy of the object each time...
        // So returning a `foo&` returns a *reference* to this, and operates on
        // the *same* object each time.
        foo& Add(int n)  
        {
            num += n;
            std::cout << num << std::endl;
            // If you actually DO need a pointer, 
            // change the return type and do not dereference `this`
            return *this;  
        }
    private:
        int num;
};

int main()
{
    foo f;
    f.Add(10).Add(5).Add(3);
    return 0;
}

Which outputs:

$ ./a.out
10
15
18
Mark Rushakoff
jmucchiello
Thanks for your help everyone :)
Sam
AndreyT
Mark Rushakoff
+4  A: 

Another example is the Named Parameter Idiom.

Steve Fallows
Dan
A: 
#include <iostream>

using namespace::std;

class Print
{
    public:
     Print * hello();
     Print * goodbye();
     Print * newLine();
};

Print * Print::hello()
{
    cout << "Hello";
    return this;
}
Print * Print::goodbye()
{
    cout << "Goodbye";
    return this;
}
Print * Print::newLine()
{
    cout << endl;
    return this;
}

int main (void)
{
    Print print;
    print.hello()->newLine()->goodbye()->newLine();

    return 0;
}

Output:

   Hello
   Goodbye
Håkon