web-dev-qa-db-ja.com

関数ポインタ型を返す

多くの場合、関数ポインターを返す関数を作成する必要があります。私が行うときはいつでも、私が使用する基本的なフォーマットは次のとおりです。

_typedef int (*function_type)(int,int);

function_type getFunc()
{
   function_type test;
   test /* = ...*/;
   return test;
}
_

しかし、これは多数の関数を扱うときに面倒になる可能性があるので、それぞれ(または関数の各クラス)に対してtypedefを宣言する必要はありません。

Typedefを削除し、関数で返されるローカル変数を次のように宣言できます。int (*test)(int a, int b);関数の本体を次のようにします。

_{
     int (*test)(int a, int b);
     test /* = ...*/;
     return test;
}
_

しかし、その後、関数の戻り値の型に何を設定するのかわかりません。私が試してみました:

_int(*)(int,int) getFunc()
{
    int (*test)(int a, int b);
    test /* = ...*/;
    return test;
}
_

しかし、それは構文エラーを報告します。関数ポインターのtypedefを宣言せずに、そのような関数の戻り値の型を宣言するにはどうすればよいですか。それも可能ですか?また、関数ごとにtypedefを宣言する方がきれいだと思われることに注意してください。ただし、コードをできるだけクリーンでフォローしやすいように構成するように非常に注意しています。 typedefを削除したい理由は、それらが検索関数の宣言にのみ使用されることが多く、そのためコード内で冗長に見えるためです。

54
S E
_int (*getFunc())(int, int) { … }
_

それはあなたが要求した宣言を提供します。さらに、 ola1olsson notesのように、voidを挿入するとよいでしょう:

_int (*getFunc(void))(int, int) { … }
_

これは、getFuncがパラメーターを取らない可能性があることを示しています。これにより、誰かがgetFunc(x, y)の代わりにgetFunc()(x, y)を誤って書き込むなどのエラーを回避できます。

59

おそらく次のようなことができます:

int foo (char i) {return i*2;}

int (*return_foo()) (char c)
{
   return foo;
}

しかし、神、私はあなたのコードをデバッグする必要がないことを願っています....

5
yosim

これは、関数ポインタを取るため、すでに与えられた答えよりも少し難しいため、ここに残してください

(int (__cdecl *)(const char *))

関数ポインタを返します

(int (__cdecl *)(const char *))

#include <stdio.h>

int (*idputs(int (*puts)(const char *)))(const char *) {
    return puts;
}

int main(int argc, char **argv)
{
    idputs(puts)("Hey!");

    return 0;
}
2
Dmitry

C++クラスでいくつかのCコードをラップしている間、元のポスターと同じ欲求がありました。関数ポインタープロトタイプをtypedef 'に頼らずに関数から関数ポインターを返します。 C++ constの正確性に問題があります。これは少し話題から外れていても(C++)、共有する価値があると思いましたが、元の質問に直接関連しています:C関数ポインターを返す構文typedefに頼る。

以下のコードは、クラスAを定義します。このクラスは、関数ポインターを格納し、get_f()呼び出しを介して外部に公開します。これは、typedefなしで関数ポインターを返す必要がある関数です。

ポイント(しばらくの間私を困惑させた)は、get_f()const関数である、つまりAを変更しないことを宣言する方法でした。

コードには2つのバリアントが含まれます。1つ目は関数ポインタープロトタイプにtypedefを使用し、2つ目はすべてを完全に書き出します。 #ifは2つを切り替えます。

#include <iostream>

int my_f(int i)
{
  return i + 1;
}

#if 0 // The version using a typedef'ed function pointer

typedef int (*func_t)(int);

class A
{
public:
  A(func_t f) : m_f(f) {}
  func_t get_f() const { return m_f; }

private:
  func_t m_f;
};

int main(int argc, char *argv[])
{
  const A a(my_f);
  std::cout << "result = " << a.get_f()(2) << std::endl;
}

#else // The version using explicitly prototyped function pointer    

class A
{
public:
  A(int (*f)(int)) : m_f(f) {}
  int (*get_f() const)(int) { return m_f; }

private:
  int (*m_f)(int);
};

int main(int argc, char *argv[])
{
  const A a(my_f);
  std::cout << "result = " << a.get_f()(2) << std::endl;
}

#endif

予想/望ましい出力は次のとおりです。

result = 3

キーポイントは、行内のconst修飾子の位置です。

int (*get_f() const)(int) { return m_f; }
1
duncan

これは馬鹿げた例ですが、簡単でエラーは発生しません。静的関数を宣言するだけです:

#include <stdio.h>
#include <stdlib.h>

void * asdf(int);
static int * hjkl(char,float);

main() {
  int a = 0;
  asdf(a);
 }


void * asdf(int a) {return (void *)hjkl; }
static int * hjkl(char a, float b) {int * c; return c;}
1
NicoM

次のコードを記述できます(C++ 11以降でのみ機能します)。

//C++11
auto func(...) {
    int (*fptr)(...) ret = ...
    //Do sth.
    return ret;//C++11 compiler will automatically deduce the return type for you
}

または、自動戻り型の推論が気に入らない場合は、関数の最後に型を指定できます(上記と同じ、C++ 11以降のみ):

//C++11
auto func(...) -> int (*)(...) { /* Do sth. */ }
0
JiaHao Xu

次の3つのオプションがあると思います。

  1. Typedefに固執します。結局のところ、それはtypedefの仕事です。
  2. Void *を返し、キャストします。
  3. ソフトウェアアーキテクチャを再検討してください。おそらく、あなたが達成しようとしていることを私たちと共有し、私たちがあなたをより良い方向に向けることができるかどうかを見ることができます。
0
Raffaele Rossi