関数がFoo::print()
で静的に呼び出されるか、Foo foo; foo.print();
のインスタンスから呼び出されるかに応じて、2つの異なるものを出力したいと思います。
編集:これは確かに機能しないクラス定義です。すでに数人が回答しています。
class Foo {
string bla;
Foo() { bla = "nonstatic"; }
void print() { cout << bla << endl; }
static void print() { cout << "static" << endl; }
};
しかし、この効果を達成するための良い方法はありますか?基本的に、私はしたいと思います:
if(this is a static call)
do one thing
else
do another thing
別の言い方をすると、PHPが*this
変数は、関数が静的に呼び出されるかどうかを決定するために定義されているかどうかを示します。 C++には同じ機能がありますか?
いいえ、それは規格によって直接禁止されています:
ISO 14882:2003 C++ Standard 13.1/2 –オーバーロード可能な宣言
特定の関数宣言はオーバーロードできません:
- 戻りの型のみが異なる関数宣言はオーバーロードできません。
- 同じ名前と同じパラメーター型のメンバー関数宣言は、それらが
static
メンバー関数宣言(9.4)である場合はオーバーロードできません。...
[例:
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
};
-例を終了]
...
さらに、インスタンスで静的関数を呼び出すことができるため、いずれにしてもあいまいになります。
ISO 14882:2003 C++ Standard 9.4/2 –静的メンバー
クラス
s
の静的メンバーX
は、qualified-id式X::s
を使用して参照できます。 ;static member
を参照するためにクラスメンバーアクセス構文(5.2.5)を使用する必要はありません。static
メンバーは、クラスメンバーアクセス構文を使用して参照できます。その場合、object-expression
が評価されます。 [例:
class process {
public:
static void reschedule();
}
process& g();
void f()
{
process::reschedule(); // OK: no object necessary
g().reschedule(); // g() is called
}
-例を終了]
...
だから、あなたが持っているものには曖昧さが存在します:
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();
}
メンバー関数が呼び出されているインスタンスを確認できるかどうかという質問に対処するために、this
キーワードがあります。 this
キーワードは、関数が呼び出されたオブジェクトを指します。ただし、this
キーワードは常にオブジェクトを指します。つまり、NULL
になることはありません。したがって、関数が静的に呼び出されているのか、PHP以外で呼び出されているのかを確認することはできません。
ISO 14882:2003 C++ Standard 9.3.2/1 – thisポインター
非静的(9.3)メンバー関数の本体では、キーワード
this
は非値の式であり、その値は関数が呼び出されるオブジェクトのアドレスです。
絶対に許可されていません。私はこれを達成するためのきれいな方法を見ていません。この方法で解決したい問題は何ですか?
正確にそれを行うことはできません。 インシリコの答え を参照してください。
ただし、Foo::print()
とFoo foo; print(foo);
に異なる処理をさせることができます。 (void print(Foo& foo)
を_class Foo
_と同じ名前空間で定義します。ADLによって検出されます)。
いずれにしても、これは良い考えではありません。名前が非常に似ている2つの関数があり、それらはまったく異なることを行うため、優れた設計原則に違反しています。
戻り値の型に基づいてオーバーロードすることはできないため、答えはノーです。
確かにクラスに静的メソッドを含めることはできますが、以下を含めることはできません。
static void foo();
void foo();
同じメソッドシグネチャがあるためです。
編集:なぜこれを行いたいのか、そしてメンバー変数にアクセスしたいのかというコメントを見ました。これを行う必要があります:
static void print(Foo f);
void print();
....
static void Foo::print(Foo f)
{
int a = f.a;
// do something with a
}
(またはFooなどでゲッターとセッターを作成しますが、それが一般的な考えです)