2

私がクラスを持っているとしましょう:

class A
{
public:
  void doSomething();
}

doSomethingは、Aのインスタンスの内部状態に明示的に依存する何かを実行します。

今、私はタイプAのものがたくさんある状況にありますが、それらの厳密なサブセットからdoSomethingを呼び出したいだけなので、それらをリストに残したいと思います。特に、私が本当にやりたいのは、リスト内の個々のdoSomethings()へのポインターを固定することです。

できますか? 私はそれを次のように宣言しますか?

std::list<(A::*)()> aDoSomethings;

私はこのエントリを読みました、それは理にかなっています、そして私が必要なら私はそのルートに行きます。

4

6 に答える 6

3

単純なOOアプローチを検討しましたか?

struct Can_Do_Something
{
    virtual void doSomething() = 0;
};

class A : public Can_Do_Something
{
    ...
};

std::list<Can_Do_Something*> my_list;

my_list[n]->doSomething();

これにより、リストを介してアクセスする予定のAのインターフェイスの一部(Can_Do_Somethingタイプを介して継承)へのアクセスが制限的に維持されます。それはその制限を文書化し、実施します。

元のビジョンに近いものを好む場合は、次のことを検討してください...

#include <iostream>
#include <vector>
#include <boost/function.hpp>

struct A
{
    A(int n) : n_(n) { }

    int f(int x) { std::cout << "A::f() this " << (void*)this
                           << ", n_ " << n_
                           << ", x_ " << x << '\n'; }

    int n_;
};

int main()
{
    typedef boost::function<int (int n)> Function;
    typedef std::vector<Function> Functions;

    Functions functions;
    A a1(1), a2(2), a3(3);

    functions.push_back(std::bind1st(std::mem_fun(&A::f), &a1));
    functions.push_back(std::bind1st(std::mem_fun(&A::f), &a2));
    functions.push_back(std::bind1st(std::mem_fun(&A::f), &a3));

    for (Functions::iterator i = functions.begin();
            i != functions.end();
            ++i)
        (*i)(42);
}

ここで、boost :: functionは、関心のある特定の関数へのコールバックを作成するために使用されます。

于 2010-09-15T18:29:27.120 に答える
2

メンバー関数ポインタがどのように機能するかについて混乱しているようです。特定のクラスに対して、特定の関数のインスタンスは1つだけです。これらは、暗黙的なパラメータを使用することで区別されますthis。基本的に、次のマッピングがあるふりをすることができます。

struct Struct { void Function(); }
Struct a;
a.Function();

になる

struct Struct { }
void Function(Struct* this);
Struct a;
Function(&a);

したがって、多数のStructオブジェクトがあり、それらの小さなセットを呼び出したいFunction場合は、保存せずに保存FunctionしますStruct

メンバー関数へのポインターは、選択的に呼び出したい複数の関数がある場合に使用されます。したがって、クラスに2つの関数があり、どちらもパラメーターを受け取らず、voidを返す場合は、void (Struct::*)()どちらかを指すことができます。しかし、それでも特定の機能を指し示しており、そのうちの1つしかありません。それでもパラメータを指定する必要がありthisます。

struct Struct {
  Struct(int v) : value(v) { }
  void One() { cout << "one: " << value << endl; }
  void Two() { cout << "two: " << value << endl; }
  int value;
};

int main()
{
  std::vector<Struct> v;
  v.push_back(1);
  v.push_back(2);
  v.push_back(3);

  std::vector<void (Struct::*)()> f;
  f.push_back(&Struct::One);
  f.push_back(&Struct::Two);
  f.push_back(&Struct::One);

  for(int i = 0; i < 3; ++i)
    (v[i].*f[i])();
}  

最良の例ではありませんが、それは重要な意味を持ちます。メンバー関数を使用して、オブジェクトを組み合わせて組み合わせることができます。

*編集:コンテナが邪魔にならない例

Struct a(5), b(10);
void (Struct::*one)() = &Struct::One;
void (Struct::*two)() = &Struct::Two;

(a.*one)();
(b.*one)();
(a.*two)();
(b.*two)();

余分な括弧に注意してください。 a.*one()不十分です。

于 2010-09-15T19:27:50.277 に答える
1

thisメンバー関数ポインターには、特定のインスタンスへのポインターがありません。ポインターとパラメーターを指定して、特定のシグニチャーを使用してメンバー関数を呼び出す方法について説明します。

代わりに、関心のあるオブジェクトへのポインターをリストに入れてから、そのリストを繰り返し処理して、doSomething各アイテムを呼び出します。

于 2010-09-15T18:30:17.873 に答える
1

boost::functionとboost::bindをチェックする必要があります。

于 2010-09-15T18:35:50.000 に答える
0

はい、おそらく次のようなものが必要です。

#include <vector>
#include <iostream>
#include <string>

using namespace std;

class A {
  string m_name;

  public:
    A(const string& name) : m_name(name) {} 
    void doSomething() { cout << m_name << "::doSomething()" << endl; }
};

int main(void) {
  A f1("f1");
  A f2("f2");
  A f3("f3");
  A f4("f4");
  vector<A*> foo_list;
  foo_list.push_back(&f1);
  foo_list.push_back(&f3);

  for (vector<A*>::iterator it = foo_list.begin(); it != foo_list.end(); *it++) {
    static_cast<A*>(*it)->doSomething();
  }

  return 0;
}
于 2010-09-15T18:28:55.507 に答える
0

私の理解が正しければ、doSomething()でなければならない関数メンバーへのポインターのリストが必要ですか?

次に、クラスのメンバーへの関数ポインターのリストを作成できますが、関連するオブジェクトを提供する必要があるので、単にオブジェクトのリスト(ポインター)を保持してみませんか?

于 2010-09-15T18:29:18.917 に答える