2010-11-19 11 views
27

構造体に関数が含まれていますか?構造内の関数

+0

通常のCプログラミングでは可能ですが、本来の利点はありません。 Cでは、すべての関数は大域的な空間にあるため、関数にそれらを入れて情報を隠すことはありません。 paxdiabloの例は、関数を構造体に編成する方法ですが、使用するには、関数を逆参照する必要があります。 Cの標準的な組織構造はFileで、ヘッダには のインタフェースとソース内の実装があります。 これはlibcがどのように行われ、どのようにほとんどすべてのCライブラリが実行されるかです。 –

答えて

33

いいえ、しかし、それらは機能ポインタを含むことができます。あなたの目的はCで多型のいくつかのフォームを行うのであれば

は[はい、行うことができます。

typedef struct { 
    int (*open)(void *self, char *fspec); 
    int (*close)(void *self); 
    int (*read)(void *self, void *buff, size_t max_sz, size_t *p_act_sz); 
    int (*write)(void *self, void *buff, size_t max_sz, size_t *p_act_sz); 
    // And data goes here. 
} tCommClass; 

上記typedef私は汎用の通信ライブラリ用に作成された構造のためでした。変数を初期化するために、あなたが希望:

tCommClass *makeCommTcp (void) { 
    tCommClass *comm = malloc (sizeof (tCommClass)); 
    if (comm != NULL) { 
     comm->open = &tcpOpen; 
     comm->close = &tcpOpen; 
     comm->read = &tcpOpen; 
     comm->write = &tcpWrite; 
    } 
    return comm; 
} 

tCommClass *makeCommSna (void) { 
    tCommClass *comm = malloc (sizeof (tCommClass)); 
    if (comm != NULL) { 
     comm->open = &snaOpen; 
     comm->close = &snaOpen; 
     comm->read = &snaOpen; 
     comm->write = &snaWrite; 
    } 
    return comm; 
} 

tCommClass *commTcp = makeCommTcp(); 
tCommClass *commSna = makeCommSna(); 

次に、関数を呼び出すために、のようなもの:このように

// Pass commTcp as first params so we have a self/this variable 
// for accessing other functions and data area of object. 
int stat = (commTcp->open)(commTcp, "bigiron.box.com:5000"); 

、シングルタイプはTCP、SNA、RS232を使用することができますまたはキャリアピギーゴンであっても、まったく同じインターフェースである。

+1

これはまた、構造体とクラスの違いの1つですか?なぜなら、違いは構造体がデフォルトのpublicを持ち、クラスがデフォルトのprivate – JoshMachine

+0

@Joshだから、あなたはpublic/privateがC++の構造体/共用体の唯一の違いだと思います。この質問はCに関するものでした。私は 'struct xyz {int fn(void); } a; 'g ++で正常に動作しました。 – paxdiablo

+0

ああ、私はCのタグを見ませんでした。 +1疑惑をクリアするために! – JoshMachine

5

編集「は、データタイプ」

C.にstruct種類しか格納できないデータを用いて曖昧さをクリア。

ISO C99標準のセクション6.7.2.1より。

構造又は組合が不完全または機能タイプ付き部材を含んではならない(従って、 構造自体のインスタンスを含んではならない、それ自体のインスタンス へのポインタを含んでいてもよい)、除きます複数の名前付きメンバ を持つ構造の最後のメンバーが不完全な配列型を持つ可能性があります。そのような構造体(および可能であれば を含む任意の共用体は、そのような構造体であるメンバー)は、構造体のメンバーでも配列の要素でもないものとする。

+0

標準を指摘するための+1 – Jay

+0

「データ型を含む」は、(少なくともC++ユーザーにとって、型を宣言することができる)危険で曖昧です。すべて標準でクリアされていますが... :-)。 –

0

Cでは、構造体にはデータ値が含まれ、関数ポインタは含まれません。 C.では許可されていませんが、gccでチェックすると次のように動作します。だから、混乱してい

enter code here 

#include <stdio.h> 

struct st_func_ptr{ 
     int data; 
     int (*callback)(); 
}; 

int cb(){ 
     printf(" Inside the call back \n"); 
     return 0; 
} 

int main() { 
     struct st_func_ptr sfp = {10, cb}; 

     printf("return value = %d \n",sfp.callback()); 

     printf(" Inside main\n"); 
     return 0; 
} 

...

+1

誰が 'C 'の構造体に関数ポインタを持つことができないのですか? – detly

+2

はい、あなたは物事を混ぜているようです。関数ポインタは許され、関数自身は機能しません。 –

+0

コールバックは、intを返す0パラメータを持つ関数へのポインタです。 Cは、関数シグネチャ に一致する関数を参照することによって、コールバックに割り当てることができます。 初期化リストの使用はここで新しく特別なものです。 printfステートメントは有効なCですが、スタイルは正しくありません。 の意図については混乱しています。構造体の定義から遠く離れているのを見た場合、それが何であったのか疑問に思って狩りをしなければならないかもしれません。 –

0

それはすべての権利です。 Linuxのカーネルコードでは、多くの構造に関数が含まれています。 のような:

+0

さて、それらは関数のポインタです。それらを初期化するために何らかの努力を払うことを除いて、まったく同じです。NULLであるか無効な場合にそれらを使用しようとするリスクがあり、実行時に変更することができます。 .. –

0
/* 


* The type of device, "struct device" is embedded in. A class 
* or bus can contain devices of different types 
* like "partitions" and "disks", "mouse" and "event". 
* This identifies the device type and carries type-specific 
* information, equivalent to the kobj_type of a kobject. 
* If "name" is specified, the uevent will contain it in 
* the DEVTYPE variable. 
*/ 
struct device_type { 
     const char *name; 
     struct attribute_group **groups; 
     int (*uevent)(struct device *dev, struct kobj_uevent_env *env); 
     void (*release)(struct device *dev); 
     int (*suspend)(struct device * dev, pm_message_t state); 
     int (*resume)(struct device * dev); 
}; 

はいその可能な機能を宣言すると、関数定義は許可されていない、それは関数ポインタであるべきです。

これはC99タグ構造に基づいています。

ロークシュV

0

彼らはすることができますが、何の固有の利点は、通常のCプログラミングではありません。

Cでは、すべての関数はグローバルな空間にあるため、関数に埋め込むことで情報を隠すことはありません。paxdiabloの例は、関数を構造体に編成する方法ですが、使用するには、関数を逆参照する必要があります。

Cの標準的な組織構造はFileで、 のヘッダーのインターフェイスとソースの実装です。

これはlibcがどのように行われ、どのようにほとんどすべてのCライブラリが実行されるかです。

Moder Cコンパイラでは、同じソースファイル内に関数を定義して実装したり、ヘッダファイルに静的関数を実装することさえできます。これは残念なことに、何がどこへ行くのかに関するいくつかの混乱につながり、関数を構造体に詰め込み、ヘッダーのないソースのみのプログラムなどのような珍しい解決策を得ることができます。 実装をそのように実装する利点を失います。

0

いいえあなたはできません。ストラクチャは関数の宣言を含むことはできませんが、関数の定義を含むことができます。ストラクチャはデータ型、ポインタ、異なる関数へのポインタのみを含みます。関数へのポインタを作成し、構造からアクセスすることができます。

#include<iostream> 
#include<cstring> 
using namespace std; 

struct full_name 
{ 
    char *fname; 
    char *lname; 
    void (*show)(char *,char*); 
}; 

void show(char *a1,char * a2) 
{ 
    cout<<a1<<"-"<<a2<<endl; 
} 

int main() 
{ 

struct full_name loki; 
loki.fname="Mohit"; 
loki.lname="Dabas"; 
loki.show=show; 
loki.show(loki.fname,loki.lname); 


return 0; 

} 
関連する問題