Vấn đề không phải là với việc chuyển đổi từ một trong hai LeftSide
hoặc RightSide
để Side<T>
. Như bạn nghĩ ban đầu, chuyển đổi này sẽ ổn.
Thay vào đó, vấn đề là với biểu thức này:
left < right ? new LeftSide<int> : new RightSide<int>
Hãy phá vỡ này xuống một chút. Toán tử bậc ba (được gọi đúng trong Chuẩn như 'toán tử so sánh') trông giống như sau:
bool_val ? lhs_expression : rhs_expression
Hãy nhớ rằng toàn bộ cấu trúc này chính là biểu thức. Có nghĩa là nó trả về một giá trị, mà phải có một loại, obv. Loại biểu thức toàn bộ được suy ra từ các loại lhs_expression
và rhs_expression
. Trong trường hợp này, bạn có LeftSide
và RightSide
. Vì vậy, đây là vấn đề của bạn.
LeftSide
và RightSide
không liên quan trực tiếp với nhau ngoài việc có lớp cơ sở chung và không có chuyển đổi nào giữa chúng. (Bạn sẽ phải viết một.) Vì vậy, không có datatype duy nhất mà bool_val ? lhs_expression : rhs_expression
có thể có. Bạn có thể nghĩ, "tốt, trình biên dịch ngớ ngẩn, tại sao không chỉ tìm ra lớp cơ sở chung và sử dụng nó?" Đây thực sự là một nỗi đau. Để lại lập luận của nó là Đúng hay Sai sang một bên, nó không hoạt động theo cách đó.
Bạn có hai tùy chọn.
One, sử dụng một cấu trúc đơn giản hơn:
if(left < right)
return new LeftSide<int>;
else
return new RightSide<int>;
Hai, nếu bạn thực sự thực sự muốn sử dụng các nhà điều hành ternary (đó là trường hợp đôi khi), bạn cần phải muỗng thức ăn chăn nuôi trình biên dịch đó là kiểu dữ liệu:
Side<int>* f(int left, int right)
{
return left < right ? static_cast<Side<int>*>(new LeftSide<int>) : static_cast<Side<int>*>(new RightSide<int>);// now you're good
}
(1) Bạn không thể viết chuyển đổi do người dùng xác định các kiểu con trỏ. (2) Bạn chỉ cần sửa kiểu của một toán hạng để nó hoạt động. (3) Thậm chí 'static_cast' là quá mức cần thiết vì một chuyển đổi ẩn tồn tại, và' static_cast' có thể ngăn cản trình biên dịch cảnh báo về các vấn đề an toàn kiểu hợp pháp. –