C++ surcharge statique fonction avec non-statique fonction

Je voudrais imprimer deux choses différentes selon qu'une fonction est appelée statiquement avec Foo::print() ou à partir d'une instance de Foo foo; foo.print();

EDIT: Voici une définition de classe qui ne fonctionne certainement pas, comme répondu par quelques personnes déjà.

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

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

Cependant, est-il un bon moyen d'obtenir cet effet? Fondamentalement, je voudrais faire:

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

Formulé d'une autre manière, je sais que PHP peut vérifier si la variable *this est définie ou non pour déterminer si la fonction est appelé statiquement. Est-ce que C++ a la même capacité?

30
demandé sur Alan Turing 2011-03-20 02:36:06

4 réponses

Non, il est directement interdit par la norme:

ISO 14882: 2003 norme C ++ 13.1 / 2-déclarations Superposables

Certaines déclarations de fonction ne peuvent pas être surchargé:

  • les déclarations de fonction qui ne diffèrent que par le type de retour ne peuvent pas être surchargées.
  • les déclarations de fonctions membres portant le même nom et les mêmes types de paramètres ne peuvent pas être surchargées si l'un d'entre eux est une déclaration de fonction membre static (9.4).

...

[Exemple:

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
};

-exemple de fin]

...

D'ailleurs, ce serait ambigu de toute façon puisqu'il est possible d'appeler des fonctions statiques sur les instances:

ISO 14882: 2003 norme C++ 9.4 / 2-membres statiques

Un membre statique s de la classe X peut être référencé à l'aide du qualified-id expression X::s; ce n'est pas nécessaire pour utiliser la syntaxe d'accès des membres de classe (5.2.5) pour désigner un static member. Un static Membre peut être référé à l'aide la syntaxe d'accès des membres de la classe, dans quel cas le object-expression est évaluer. [Exemple:

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

-exemple de fin]

...

Il y aurait donc une ambiguïté avec ce que vous avez:

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();
}

Pour répondre à votre question de savoir si vous pouvez vérifier quelle instance une fonction membre est en cours appelé, il y a le mot clé this. Le mot clé this pointe vers l'objet pour lequel la fonction a été invoquée. Cependant, le mot clé this pointera toujours vers un objet, c'est-à-dire qu'il ne sera jamais NULL. Par conséquent, il n'est pas possible de vérifier si une fonction est appelée statiquement ou non à la PHP.

ISO 14882: 2003 C++ Standard 9.3.2 / 1-ce pointeur

Dans le corps d'un non statique (9.3) fonction membre, le mot-clé this est un non lvalue expression dont la valeur est l'adresse de l'objet pour lequel la fonction est appelée.

52
répondu In silico 2011-03-20 00:16:32

Ce n'est certainement pas autorisé. Je ne vois aucun moyen propre d'y parvenir. Quel est exactement le problème que vous voulez résoudre de cette façon?

2
répondu Janick Bernet 2011-03-19 23:41:09

Vous ne pouvez pas faire cela exactement, voir dans la réponse de silico .

, Mais vous pouvez faire Foo::print() et Foo foo; print(foo); faire des choses différentes. (Définissez void print(Foo& foo) dans le même espace de noms que class Foo, il sera trouvé par ADL).

En tout cas, ce n'est pas une bonne idée. Vous avez deux fonctions très similaires dans le nom qui font des choses complètement différentes, ce qui viole les bons principes de conception.

1
répondu Ben Voigt 2017-05-23 12:18:19

La réponse est non, car vous ne pouvez pas surcharger en fonction d'un type de retour.

Vous pouvez certainement avoir des méthodes statiques dans une classe, mais vous ne pouvez pas avoir:

static void foo();
void foo();

Parce Qu'ils ont la même signature de méthode.

EDIT: j'ai vu votre commentaire disant pourquoi vous avez voulu faire cela, et que vous vouliez accéder aux variables membres. Vous devez faire ceci:

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

(ou créer des getters et des setters dans Foo, etc, mais c'est l'idée générale)

1
répondu Brian Roach 2011-03-20 00:00:36