13

次のようにCで構造体を宣言できます。

typedef struct MyStruct {
    const char *name;
    int (*func1)(void);
    int (*func2)(void);
    int (*func3)(void);
} MyStruct;

int test_func2(void) {
    return 0;
}

MyStruct test_struct = {
    .name   = "buffer",
    .func2  = test_func2,
};

これは、特定のメンバーのみを定義する場合に非常に便利です。他のすべてのメンバーは0/NULLに設定されます。

編集:特に、これによりMyStructがどのように定義されているかを詳細に知ることができないため、このタイプを使用してコードを壊すことなく、内部で変更したり、新しいメンバーを追加したりできます。

ただし、これはC ++コンパイラではコンパイルされませんが、エラーが発生します。

test.c:23: error: expected primary-expression before ‘.’ token
test.c:24: error: expected primary-expression before ‘.’ token

同じことを達成する同等のC++宣言はありますか?

ありがとう。

編集:@chris私はあなたが理解していないと言うことができます:)そして、私がどの構文を使うべきか、構造がどのように定義されるべきかなどについてコメントする他のほとんどの人々が完全に要点を見逃していることは明らかです。これは構造を定義する正しい方法ではありません。このスニペットはコンテキストを提供するためだけにありました。

コードの同等性については、コードのどこかで次のように言ってください。

MyStruct blah = { NULL, NULL, func2 };

MyStructは、その定義を次のように変更します。

typedef struct MyStruct {
  const char *name;
  int (*func4)(void);
  int (*func1)(void);
  int (*func2)(void);
  int (*func3)(void);
} MyStruct;

コードは引き続き正常にコンパイルされますが、深刻なリグレッションが発生します。以前のようにfunc2を設定する代わりに、func1メンバーを初期化するようになりました...

質問は、同等のC++指定の初期化子があるかどうかについてでした。ありません。問題は解決しました。

4

4 に答える 4

16

いいえ、C++はC99の指定された初期化子をサポートしていません。個々のメンバーを名前で設定する場合は、割り当てを介して設定する必要があります。

MyStruct test_struct = MyStruct();
test_struct.name  = "buffer";
test_struct.func1 = test_func1;
于 2012-06-02T01:51:28.820 に答える
2

K-balloが言ったように、コードは次のものと同等です。

MyStruct test_struct = {
    "buffer",
    test_func1
};

ただし、C ++を使用しているため、MyStructのコンストラクターの作成と使用を検討する必要があります。

struct MyStruct {
    const char *name;
    int (*func1)(void);
    int (*func2)(void);
    int (*func3)(void);

    MyStruct(const char *n,
        int (*f1)(void) = NULL,
        int (*f2)(void) = NULL,
        int (*f3)(void) = NULL) : name(n), func1(f1), func2(f2), func3(f3) {}
};

C ++では、MyStructにtypedefする必要はなく、typedefがなくても(structキーワードなしで)MyStructを使用できることに注意してください。

于 2012-06-02T01:58:13.747 に答える
2

ラムダを使用できます(C ++ 11以降)。これにより、構造のグローバル/定数インスタンスを簡単に初期化しながら、宣言をそのままにしておくことができます。

struct Test
{
    int x;
    float y;
};

const Test test=[]{ Test t{}; t.x=5, t.y=3.3465; return t; }();

#include <iostream>
int main()
{
    std::cout << "test.x: " << test.x << ", test.y: " << test.y << "\n";
}

これをマクロにラップすることもできますが、以下の形式では、固定数の初期化子のみが許可されます。

// Macro to simplify it a bit
#define DECL_AND_INIT(Type,object,INIT1,INIT2) \
Type object=[]{ Type o{}; o.INIT1; o.INIT2; return o; }()
// Example usage
const DECL_AND_INIT(Test,test1,x=-7,y=-9.325e31);

ラムダのように値の初期化を使用する必要があることに注意してください。Test t{};そうしないと、すべてのメンバーを初期化しない場合(たとえば、新しいメンバーが追加されたため)、初期化されていない変数がコピーされてUBになります。

于 2016-09-27T11:23:44.843 に答える
1

structこれと同等の機能は、本体が空の場合のコンストラクターになります。

#ifdef __cplusplus
MyStruct::MyStruct(char* N, int (*F)(void)) :
    name(N),
    func1(0),
    func2(0),
    func3(F) {
  // empty
}
#endif

(いくつかの構文エラーを法として、私のC ++は少し錆びています。)

これは、修飾されたフィールドがある場合でもグローバルオブジェクトを構築できるため、機能的には同等です。const最新のコンパイラでは、コンパイル時に静的リンケージを使用してオブジェクトを初期化する必要があります。

于 2012-06-02T08:24:33.713 に答える