4

私は C++ の学習を支援する方法として irc ボットに取り組んでおり、次のようにメソッドを変数として使用できるかどうか疑問に思っていました。

//Irc.h
public:

void *onJoin(char* sender, char* channel);
/////

//Main.cpp
void join(char* sender, char* channel)
{
    cout << sender << endl;
    cout << channel << endl;
}
int main()
{
    Irc irc(stuff);
    irc.onJoin = join;
}
4

4 に答える 4

8

はい、可能です。これらの変数は関数ポインタと呼ばれます。は次のように記述できます。

void onJoin( char* sender, char * channel );

int main(void)
{
    void (*func)(char *,char *);
    func = &onJoin;
    func( "sender", "channel" );
}

または、そのために使用することもできますstd::function<>main()に置き換えられる最初の行を除いて、コードは同じです。

    std::function<void(char*,char*)> func;

これは私の意見ではもう少し読みやすいです。これを使用する場合は、追加することを忘れないでください

#include <functional>

ファイルの先頭に。このような変数を関数で使用する代わりに、それらを anystructまたはのメンバー変数として使用することもできますclass

于 2013-06-05T15:56:20.900 に答える
4

関数へのポインタが必要です。

void* (*OnJoinFn)(char*, char*);

あなたのIrcクラスでは、

class Irc
{
public:
  OnJoinFn onJoin;
};

これは、上記のように割り当てることができます。

int main()
{
    Irc irc(stuff);
    irc.onJoin = join;
}

しかし、C++ を学んでいるだけなら、関数へのポインタが本当に必要なのだろうか? 関数へのポインターは確かに合法で有効ですが、珍しいエンティティであり、通常は他のメカニズムを使用することを期待しています。まず、抽象基本クラスを調べることをお勧めします。

class IIrc
{
public:
  virtual void* OnJoin(const char*, const char*) = 0;  // pure virtual
  virtual ~IIrc() {}; // Don't forget to implement a virtual destructor in any ABC
};

class MyIrc 
:
  public IIrc
{
public:
  void* OnJoin(const char* sender, const char* channel*)
  {
    // YOUR CODE HERE
  }
};

int main()
{
  IIrc* irc = new MyIrc;
  irc->OnJoin (...);
}

自由に const の正確性を導入しましたOnJoin

また、C++ のタイプ セーフ メカニズムのほとんどをバイパスする を返すのvoid*ではなく、実際のオブジェクトまたは別のインターフェイスへのポインターを返すことも検討する必要があります。

最後に、new(anddeleteが欠落しているため、メモリ リークが発生します) を使用することは、お粗末な方法です。代わりに、スタックに物を割り当てるか、動的な割り当てが本当に必要な場合はスマート ポインターを使用することをお勧めします。

于 2013-06-05T16:03:10.413 に答える
1

これは可能ですが、これを行う必要がある場合は、何か間違ったことをしている可能性が高いことをお勧めします。「さまざまな状況でさまざまな方法でこれを行う必要がある」ための典型的な C++ の方法は、継承を使用することです。

irc.h で:

   class ircBase
   {
     public:
      ... 
      virtual void onJoin(char *sender, char *channel) = 0;

   };

ircXX.h で:

   class ircXX: public ircBase
   {
     public:
      ... 
       virtual void onJoin(char *sender, char *channel)
       {
          cout << sender << endl;
          cout << channel << endl;
       }

   };

ircYY.h で:

   class ircYY: public ircBase
   {
     public:
      ... 
       virtual void onJoin(char *sender, char *channel)
       {
           ... do something else ... 
       }

   };

次に、必要なものに適した種類のオブジェクトを作成します。

于 2013-06-05T16:02:55.737 に答える
0

あなたが探しているのは関数ポインタです:

class Irc
{
    public:
        void (*on_join)(char*, char*);
    //  ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^
};

void join(char*, char*);

int main()
{
    Irc irc(stuff);
    irc.on_join = join;
}

std::functionまたは、キャプチャ/非キャプチャラムダを渡すことができるように使用できます。

#include <functional>

class Irc
{
    public:
        std::function<void (char*, char*)> on_join;
    //  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
};

int main()
{
    Irc irc(stuff);
    irc.on_join = [] (char* sender, char* channel)
    {
        std::cout << sender  << std::endl;
        std::cout << channel << std::endl;
    };
}
于 2013-06-05T23:46:26.640 に答える