44

I would like to print two different things depending on whether a function is called statically with Foo::print() or from an instance of Foo foo; foo.print();

EDIT: Here is a class definition that definitely does not work, as answered by a few people already.

class Foo {
    string bla;
    Foo() { bla = "nonstatic"; }

    void print() { cout << bla << endl; }
    static void print() { cout << "static" << endl; }
};

However, is there a good way of achieving this effect? Basically, I would like to do:

if(this is a static call)
    do one thing
else
    do another thing

Phrased in another way, I know PHP can check if the *this variable is defined or not to determine whether the function is called statically. Does C++ have the same capability?

Alan Turing
  • 12,223
  • 16
  • 74
  • 116
  • 2
    both versions of `print()` bear the same signature. And I don't think they can be overloaded this way. – Mahesh Mar 19 '11 at 23:43

5 Answers5

65

No, it is directly prohibited by the standard:

ISO 14882:2003 C++ Standard 13.1/2 – Overloadable declarations

Certain function declarations cannot be overloaded:

  • Function declarations that differ only in the return type cannot be overloaded.
  • Member function declarations with the same name and the same parameter types cannot be overloaded if any of them is a static member function declaration (9.4).

...

[Example:

class X {
    static void f();
    void f();                // ill-formed
    void f() const;          // ill-formed
    void f() const volatile; // ill-formed
    void g();
    void g() const;          // OK: no static g
    void g() const volatile; // OK: no static g
};

—end example]

...

Besides, it would be ambiguous anyway since it's possible to call static functions on instances:

ISO 14882:2003 C++ Standard 9.4/2 – Static members

A static member s of class X may be referred to using the qualified-id expression X::s; it is not necessary to use the class member access syntax (5.2.5) to refer to a static member. A static member may be referred to using the class member access syntax, in which case the object-expression is evaluated. [Example:

class process {
public:
        static void reschedule();
}
process& g();
void f()
{
        process::reschedule(); // OK: no object necessary
        g().reschedule();      // g() is called
}

—end example]

...

So there would be ambiguity with what you have:

class Foo
{
public:
    string bla;
    Foo() { bla = "nonstatic"; }
    void print() { cout << bla << endl; }
    static void print() { cout << "static" << endl; }
};

int main()
{
    Foo f;
    // Call the static or non-static member function?
    // C++ standard 9.4/2 says that static member
    // functions are callable via this syntax. But
    // since there's also a non-static function named
    // "print()", it is ambiguous.
    f.print();
}

To address your question about whether you can check what instance a member function is being called on, there is the this keyword. The this keyword points to the object for which function was invoked. However, the this keyword will always point to an object i.e. it will never be NULL. Therefore it's not possible to check if a function is being called statically or not à la PHP.

ISO 14882:2003 C++ Standard 9.3.2/1 – The this pointer

In the body of a nonstatic (9.3) member function, the keyword this is a non-lvalue expression whose value is the address of the object for which the function is called.

In silico
  • 51,091
  • 10
  • 150
  • 143
  • Thank you for that very clear answer, but I was asking (poorly, I apologize for that) whether the behavior of a static function could be determined based on whether it's called statically or from an instance of the class. See the later part of my question. – Alan Turing Mar 19 '11 at 23:54
  • @Lex Fridman: I didn't think you asked poorly. You asked "Does C++ have the same capability?" and I answered that you can't based on the C++ standard (which *defines* the language). – In silico Mar 19 '11 at 23:59
  • I'm feeling worse and worse about my phrasing of the question, especially the title. There are actually two questions. First, is if you can overload static with non-static. THAT's what you answered very well. The second question is if you can determine whether there's an instance of the class associated with the call of the static function. As you said, you can use a static function like this: `Foo foo; foo.print();` Can i access the `foo` instance from within that call to `print();` ? – Alan Turing Mar 20 '11 at 00:04
  • @Lex Fridman: Ah, okay. You have clarified it for me, so don't worry about your phrasing. I'll answer that part. – In silico Mar 20 '11 at 00:06
2

It is definitely not allowed. I don't see any clean way of achieving this. What is exactly the problem that you want to solve this way?

Janick Bernet
  • 20,544
  • 2
  • 29
  • 55
  • It's a little complicated to explain but I have some non-static variables that I would like the static function to access when it is called from an instance of the class. I could just name the function something else and make it non-static, but I thought it would provide a nice consistent API that just has one function available to the user. Sorry if that doesn't make sense. – Alan Turing Mar 19 '11 at 23:51
  • @Lex - you seem to be misunderstanding what 'static' means. You *can't* access non-static variables with a static method; you're not dealing with an instantiation of the class. The only way to do that would be to pass an instantiation of the class to the static method. – Brian Roach Mar 19 '11 at 23:53
  • I know Brian, but you can call static members "non-statically", so instead of `Foo::print();`, use `Foo foo; foo.print();` – Alan Turing Mar 19 '11 at 23:58
  • 2
    You're not calling it "non statically" ... that's still calling the same static function in the class, and has nothing to do with the instance of the class you happen to have there. It's no different than `Foo::print();` See: http://stackoverflow.com/questions/325555/c-static-member-method-call-on-class-instance - I believe this is the source of your confusion. – Brian Roach Mar 20 '11 at 00:04
  • Ah okay, so the instance of `foo` in that case has no meaning and cannot be accessed from within `print()`. Thanks for that clarification Brian – Alan Turing Mar 20 '11 at 00:07
1

The answer is no, because you can't overload based on a return type.

You can certainly have static methods in a class, but you can't have:

static void foo();
void foo();

Because they have the same method signature.

EDIT: I saw your comment saying why you wanted to do this, and that you wanted to access member variables. You'd need to do this:

static void print(Foo f);
void print();
....
static void Foo::print(Foo f)
{
    int a = f.a;
    // do something with a
}

(Or create getters and setters in Foo, etc, but that's the general idea)

Brian Roach
  • 76,169
  • 12
  • 136
  • 161
  • But if he does that, the next maintainer will have a big WTF moment, when trying to understand why anyone prefers `Foo::print(f)` over `f.print()`. – Bo Persson Mar 20 '11 at 11:16
1

You can't do that exactly, see In silico's answer.

But you can make Foo::print() and Foo foo; print(foo); do different things. (Define void print(Foo& foo) in the same namespace as class Foo, it will be found by ADL).

In any case, this is not a good idea. You have two functions very similar in name which do completely different things, which violates good design principles.

Community
  • 1
  • 1
Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • I know it seems like bad design, because I'm not explaining precisely the problem I'm trying to solve. It actually makes sense for what I'm doing. However, in the context of C++ it may be a bad way of doing it. I know it's a good thing to do in an interpreted language like PHP. – Alan Turing Mar 20 '11 at 00:01
  • @Lex: The two functions have to be doing different things, so surely one of them can have a different name. Maybe `Foo::PrintLiveFooCount();` and `Foo foo; foo.print();`? – Ben Voigt Mar 20 '11 at 00:03
0

1) In case of different return type of functions overloading is not possible in method overloading.

2) also if we pass same parameters in the functions define under the same class then it can not be overload.

callmenikk
  • 1,358
  • 2
  • 9
  • 24