Trong C ++, các bộ khởi tạo kiểu C đã được thay thế bởi các hàm tạo mà theo thời gian biên dịch có thể đảm bảo rằng chỉ các khởi tạo hợp lệ được thực hiện (tức là sau khi khởi tạo các thành viên đối tượng là nhất quán).
Đó là một thực hành tốt, nhưng đôi khi một khởi tạo trước là tiện dụng, như trong ví dụ của bạn. OOP giải quyết điều này bằng các lớp trừu tượng hoặc các mẫu thiết kế sáng tạo .
Theo tôi, sử dụng cách bảo mật này sẽ giết chết sự đơn giản và đôi khi sự đánh đổi bảo mật có thể quá tốn kém, vì mã đơn giản không cần thiết kế tinh vi để duy trì.
Là một giải pháp thay thế, tôi đề nghị xác định các macro sử dụng lambdas để đơn giản hóa việc khởi tạo để trông gần giống như kiểu C:
struct address {
int street_no;
const char *street_name;
const char *city;
const char *prov;
const char *postal_code;
};
#define ADDRESS_OPEN [] { address _={};
#define ADDRESS_CLOSE ; return _; }()
#define ADDRESS(x) ADDRESS_OPEN x ADDRESS_CLOSE
Macro ADDRESS mở rộng thành
[] { address _={}; /* definition... */ ; return _; }()
tạo ra và gọi lambda. Các tham số macro cũng được phân tách bằng dấu phẩy, vì vậy bạn cần đặt trình khởi tạo vào dấu ngoặc và gọi như
address temp_address = ADDRESS(( _.city = "Hamilton", _.prov = "Ontario" ));
Bạn cũng có thể viết trình khởi tạo macro tổng quát
#define INIT_OPEN(type) [] { type _={};
#define INIT_CLOSE ; return _; }()
#define INIT(type,x) INIT_OPEN(type) x INIT_CLOSE
nhưng sau đó cuộc gọi hơi kém đẹp
address temp_address = INIT(address,( _.city = "Hamilton", _.prov = "Ontario" ));
tuy nhiên, bạn có thể xác định macro ADDRESS bằng cách sử dụng macro INIT chung một cách dễ dàng
#define ADDRESS(x) INIT(address,x)