Bạn thực sự có thể làm điều đó khá đơn giản, thậm chí không có C++ 11 và lambdas:
const MyClass a;
{
MyClass _a;
_a.init();
std::swap(const_cast<MyClass&>(a), _a);
}
Việc sử dụng const_cast
là phải thừa nhận là một chút của một hack, nhưng nó đã giành' t phá vỡ bất cứ điều gì như const
là một specifier khá yếu. Đồng thời, nó khá hiệu quả, vì đối tượng MyClass
chỉ đổi chỗ, không được sao chép (hầu hết các đối tượng đắt tiền để sao chép hợp lý nên cung cấp chức năng swap
và bơm quá tải std::swap
).
Nếu không có các diễn viên, nó sẽ đòi hỏi một helper:
struct Construct_Init {
operator MyClass() const
{
MyClass a;
a.init();
return a;
}
};
const MyClass a = Construct_Init();
Đây có thể là như thế này trong một hàm (cấu trúc Construct_Init
cần không được khai báo ở phạm vi không gian tên), nhưng nó là lâu hơn một chút. Bản sao của đối tượng có thể hoặc không được tối ưu hóa bằng cách sử dụng bản sao.
Lưu ý rằng trong cả hai trường hợp, giá trị trả lại của init()
bị mất. Nếu nó trả về một boolean nơi true
là thành công và false
là thất bại, nó là tốt hơn để:
if(!a.init())
throw std::runtime_error("MyClass init failed");
Hoặc chỉ cần đảm bảo để xử lý các lỗi một cách thích hợp.
Nguồn
2014-10-30 10:02:35
Câu trả lời là không. Giống như bạn, tôi muốn nó là có. – Mehrdad
Bạn cũng có thể sử dụng 'const_cast' cho lời gọi' init' để thực hiện nhanh và dơ bẩn. Tức là, khai báo đối tượng 'const' và' const_cast' xung quanh đối tượng cho lệnh 'init'. Tuy nhiên, 'const_cast' thường được coi là thực hành không tốt, và tôi phải nói rằng tôi nghĩ rằng [giải pháp templated] (http://stackoverflow.com/a/23400028/3100771) là siêu trơn. – Apriori
@Apriori Chắc chắn hành vi không xác định. Không thể const_cast đi const từ một đối tượng const được xác định và làm công cụ không const cho nó. –