3

通常のクラス階層があります。

class B
{
public:
    int x;
    B() : x(0) {}
    virtual ~B() {}
};

class D : public B
{
public:
    int y;
    D() : y(0) {}
};

そして、引数を 1 つ取る関数 - 基本クラス オブジェクトへの参照。

void b_set(B& b)
{
    b.x = 5;
}

void (D&)次に、型の関数ポインタを作成して格納したいと思いますb_set。関数ポインター呼び出しに合法的に渡されるすべてのオブジェクトも B 型でなければならないため、これは有効な操作である必要がありますが、これは許可されていません。

typedef void (*fp_d_mutator)(D&);
void fp_test(D& obj)
{
    fp_d_mutator fun = b_set; //invalid conversion from 'void (*)(B&)' to 'fp_d_mutator {aka void (*)(D&)}
    fun(obj);
}

#include <functional>
typedef std::function<void (D&)> stdfun_d_mutator;
void stdfun_test(D& obj)
{
    stdfun_d_mutator fun = b_set; //works 
    fun(obj);
}

そう...

  • その無効な変換はどうですか?
  • その無効な変換はなぜですか?
  • これが許可された場合、何が壊れる可能性がありますか?
  • そもそも std::function が問題をどのように回避するのでしょうか?
4

1 に答える 1

3

type の引数を取る関数は、 type の引数をB&取る関数ではありませんD&D&はに変換 B&できますが、同じ型ではありません。B&へのポインターとして受け取る関数へのポインターを格納できる場合D&、コンパイラーは引数をいつ変換するかをどのように認識しますか? (変換にはポインタの調整が必要になる場合があることに注意してください)

の違いstd::functionは、呼び出しシグネチャ (ここでD&は ) が関数オブジェクトの型の一部であり、呼び出されたシグネチャ (ここでB&は ) は内部ストレージの一部であることです。したがって、関数オブジェクトを適用するoperator()と、実装するコードがoperator()(D&)変換を処理します。

于 2013-03-29T18:20:23.673 に答える