Что такое эквивалент С++ для C инициализаторов?
Вы можете объявить структуру в 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 определен, поэтому он может меняться внутренне, добавляя новых членов и т.д., не нарушая при этом кода кода.
Это не будет компилироваться вместе с компилятором С++, получив ошибку:
test.c:23: error: expected primary-expression before ‘.’ token
test.c:24: error: expected primary-expression before ‘.’ token
Существует ли эквивалентная декларация С++ для достижения того же?
Спасибо.
Изменить: @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...
Вопрос был о том, есть ли инициализаторы на С++, эквивалентные: нет. проблема закрыта.
Ответы
Ответ 1
Нет, С++ не поддерживает инициализаторы, назначенные C99. Если вы хотите установить отдельные члены по имени, вам нужно сделать это через назначение, например.
MyStruct test_struct = MyStruct();
test_struct.name = "buffer";
test_struct.func1 = test_func1;
Ответ 2
Как сказал K-ballo, код эквивалентен:
MyStruct test_struct = {
"buffer",
test_func1
};
Но так как вы используете С++, вам следует написать и использовать конструкторы для 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) {}
};
Обратите внимание, что в С++ вам не нужно вводить его в MyStruct, вы можете просто использовать MyStruct (без ключевого слова struct) даже без typedef.
Ответ 3
Вы можете просто использовать лямбда (начиная с С++ 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.
Ответ 4
Функциональная эквивалентность этого будет конструктором для вашего struct
с пустым телом:
#ifdef __cplusplus
MyStruct::MyStruct(char* N, int (*F)(void)) :
name(N),
func1(0),
func2(0),
func3(F) {
// empty
}
#endif
(по модулю некоторых синтаксических ошибок, мой С++ немного ржавый.)
Это функционально эквивалентно, так как позволяет создавать глобальные объекты, даже если они имеют const
квалифицированные поля, а любой современный компилятор должен инициализировать объекты со статической связью во время компиляции.