web-dev-qa-db-ja.com

Cの構造体のコンストラクター

与えられた:

struct objStruct {
    int id;
    int value;
};

typedef struct objStruct Object;

C++コンストラクターのようなオブジェクトを割り当てて初期化するショートカットはありますか?
プリプロセッサマクロであってもかまいません。コードをこれよりも短く読みやすくするものは何でも:

Object *newObj = malloc(sizeof(Object));
// successful allocation test snipped
newObj->id = id++;
newObj->value = myValue;
38
Aillyn

Cでは、通常、これを行うコンストラクターのスタイルで関数を作成します。例(簡潔にするためにエラーチェックを省略)

Object* Object_new(int id, int value) { 
  Object* p = malloc(sizeof(Object));
  p->id = id;
  p->value = value;
  return p;
}

...
Object* p1 = Object_new(id++, myValue);
46
JaredPar

C99以降では、キャストの後にかっこで囲まれた初期化子が続く複合リテラルを使用できます。

int init_value = ...;
int init_id    = ...;
Object newObj1 = (Object){ .value = init_value, .id = init_id };
Object newObj2 = (Object){ .id = init_id, .value = init_value };

後者の2行は同じ効果を実現します-フィールドの順序は重要ではありません。これは、別のC99機能である「指定イニシャライザー」を使用しています。指定された初期化子を使用せずに複合リテラルを作成できます。

26

Cでは、構造体と同じ名前のインライン関数を宣言できます。

struct my
{
    int a;
};

inline struct my* my(int* a)
{
    return (struct my*)(a);
}

//somewhere in code
int num = 123;
struct my *sample = my(&num);
//somewhere in code

それはC++のctorsにかなり似ています。

6
grekhss
struct thingy {
   char * label;
   int x;
};

#define declare_thingy( name, label, val) struct thingy name = { label, val }

struct thingy * new_thingy(const char * label, int val) {
     struct thingy * p = malloc(sizeof(struct thingy));
     if (p) {
          p->label = label;
          p->val = val;
     }
     return p;
}
3
nategoose

staticまたはauto変数の初期化とヘッドの動的割り当てを実際に区別する必要があります。 1つ目は名前付きイニシャライザを実行し、2つ目は適切に指定されたinit関数を実行します。

すべてがうまくできます マクロにパック 簡単なstatic/auto初期化およびC++のnewに似たもの。

2
Jens Gustedt

Cを介したオブジェクト指向の「エミュレーション」を探しているなら、GObject Type System [1]を強くお勧めします。GObjectType Systemは成熟しており、たとえばGTKで広く使用されています。

GLib [2]には、現在GNOMEで使用されている小さなオブジェクト用のNiceスライスアロケーターもあります。

[1] GObject Reference Manual

[2] GLibメモリスライス

1
Tarantula