Je voudrais imprimer deux choses différentes selon que la 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 l'ont déjà répondu quelques personnes.
class Foo {
string bla;
Foo() { bla = "nonstatic"; }
void print() { cout << bla << endl; }
static void print() { cout << "static" << endl; }
};
Cependant, existe-t-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 PHP peut vérifier si le *this
variable est définie ou non pour déterminer si la fonction est appelée statiquement. C++ a-t-il les mêmes capacités?
Non, c'est directement interdit par la norme:
ISO 14882: 2003 C++ Standard 13.1/2 - Déclarations surchargeables
Certaines déclarations de fonctions ne peuvent pas être surchargées:
- 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'une d'entre elles 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
};
- fin exemple]
...
De plus, ce serait de toute façon ambigu car il est possible d'appeler des fonctions statiques sur des instances:
ISO 14882: 2003 C++ Standard 9.4/2 - Membres statiques
Un membre statique
s
de la classeX
peut être appelé à l'aide de l'expression qualifié-idX::s
; il n'est pas nécessaire d'utiliser la syntaxe d'accès aux membres de classe (5.2.5) pour faire référence à unstatic member
. Un membrestatic
peut être référencé à l'aide de la syntaxe d'accès aux membres de la classe, auquel cas leobject-expression
Est évalué. [Exemple:
class process {
public:
static void reschedule();
}
process& g();
void f()
{
process::reschedule(); // OK: no object necessary
g().reschedule(); // g() is called
}
- fin exemple]
...
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 appelée, il existe 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
. Il n'est donc 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 - Le pointeur this
Dans le corps d'une fonction membre non statique (9.3), le mot clé
this
est une expression non lvalue dont la valeur est l'adresse de l'objet pour lequel la fonction est appelée.
Ce n'est certainement pas permis. Je ne vois aucun moyen propre d'y parvenir. Quel est exactement le problème que vous souhaitez résoudre de cette façon?
Vous ne pouvez pas faire exactement cela, voir réponse de Silico .
Mais vous pouvez faire en sorte que Foo::print()
et Foo foo; print(foo);
fassent des choses différentes. (Définissez void print(Foo& foo)
dans le même espace de nom 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 leur nom qui font des choses complètement différentes, ce qui viole les bons principes de conception.
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 dire pourquoi vous vouliez 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éez des getters et setters dans Foo, etc., mais c'est l'idée générale)