5

constメンバー関数ポインターの性質をC++で定義されていますか?次の有効なコードはありますか?

struct T {
  void foo(int i) const { std::cout << i << std::endl;};
};

void (T::*f1)(int) const = &T::foo;
void (T::*f2)(int)       = reinterpret_cast<void (T::*)(int)>(f1);
T t;
(t.*f2)(1);

アップデート:

これが必要な理由は、オブジェクトとそのオブジェクトへのメンバー関数ポインターの両方を受け入れる関数を作成しているためです。constオブジェクト(const関数のみを受け入れる)のバージョンと通常のバージョンが必要です。重複したコードは必要ないので、実際のコードを非constバージョンに入れて、constバージョンから呼び出し、constを破棄するというアイデアでした。

4

5 に答える 5

3

コンパイラはそれを食べます。しかし、後方キャストの方が便利です。

繰り返しになりますが、使用しない方が良いです。 const_cast は通常、他の解決策がない場合にのみ適用する、迅速で汚い解決策です。

更新への回答

私があなたを正しく理解していれば、1 つのオブジェクトと 2 つの関数を使用することになります。最初の関数は const オブジェクトと const メンバー関数を受け入れ、2 番目 - 非 const オブジェクトと非 const メンバー関数を受け入れます。

与えられた情報に従って、非 const オブジェクトと const メンバー関数を受け入れるように 2 番目の関数を変更できます。そして、1 つの非 const オブジェクトとその const メンバー関数を与えます。

于 2012-08-11T13:10:25.397 に答える
1

はい、定義されていますが、関数が実際に const である場合は、コンパイラの最適化 (つまり、戻り値のキャッシュ) が const である関数に依存するため、必要ないかもしれません。

于 2012-08-11T13:05:41.470 に答える
0

あなたはそれを行うことができますが、それは意味がありません.f2を呼び出すことができる場所では、f1も呼び出すことができます. 別の方法でキャストする必要があります。ただし、何かがある場合は、関数ではなくオブジェクトをキャストする必要があります。

void (T::*f1)(int) const = &T::foo;
void (T::*f2)(int)       = reinterpret_cast<void (T::*)(int)>(f1);
T t;
(t.*f2)(1); // compiles
(t.*f1)(1); // this compiles too!!

しかし、もしあなたが持っているなら

const T t;
(t.*f2)(1); // error t is const
(t.*f1)(1); // still compiles
于 2012-08-11T13:27:52.660 に答える
0

あいまいさを解決する唯一の方法は、static_cast を実行することでした。これは基本的に言語機能です。

#include <boost/typeof/typeof.hpp>
struct Test
{
    const int& foo();
    const int& foo() const;
};

int main()
{
    typedef const int&(Test::*non_const_ptr)();
    typedef const int&(Test::*const_ptr)()const;
    BOOST_TYPEOF(static_cast<non_const_ptr>(&Test::foo)) ss;
}
于 2015-07-29T02:39:15.297 に答える
-1

これを行う理由はわかりません。できたとしても、より制限を厳しくするでしょう。クラス Foo があるとしましょう:

class Foo {
  void f() const;
  void g();
}

コードのスニペット:

Foo a;
const Foo b;

a.f()次に、 と の両方を呼び出すことができますが、 is のためではありa.g()ません。ご覧のとおり、メンバー関数の後に配置すると、制限が緩和されますが、制限が増えるわけではありません。b.g()bconstconst

そして、reinterpret_castこのポインターを ing することで、( の性質によりreinterpret_cast) まったく同じ値のポインターを取得し、それを呼び出そうとすると、同じ T::foo() になります。

于 2012-08-11T13:09:02.637 に答える