Là một phần tiếp theo thú vị (mặc dù không có tầm quan trọng thực tế lớn) cho câu hỏi trước đây của tôi: Tại sao C ++ cho phép chúng ta bao quanh tên biến trong ngoặc đơn khi khai báo một biến?
Tôi phát hiện ra rằng việc kết hợp khai báo trong ngoặc đơn với tính năng tên lớp được chèn có thể dẫn đến kết quả đáng ngạc nhiên về hành vi của trình biên dịch.
Hãy xem chương trình sau đây:
#include <iostream>
struct B
{
};
struct C
{
C (){ std::cout << "C" << '\n'; }
C (B *) { std::cout << "C (B *)" << '\n';}
};
B *y = nullptr;
int main()
{
C::C (y);
}
Biên dịch với g ++ 4.9.2 cho tôi lỗi biên dịch sau:
main.cpp:16:10: error: cannot call constructor 'C::C' directly [-fpermissive]
Nó biên dịch thành công với MSVC2013 / 2015 và in
C (B *)
Nó biên dịch thành công với clang 3.5 và in
C
Vì vậy, câu hỏi bắt buộc là cái nào là đúng? :)
(Tôi mạnh mẽ lắc lư theo phiên bản clang và cách msvc dừng khai báo biến sau khi chỉ thay đổi kiểu với kỹ thuật typedef của nó có vẻ kỳ lạ)
C::C
không đặt tên kiểu mà nó đặt tên cho hàm, vì vậy GCC đúng imo.
C::C y;
không có ý nghĩa, phải không? Cũng khôngC::C (y);
Tại lần đầu tiên tôi nghĩ rằng đây là một thể hiện của Đa-gây nhiều tranh cãi-Parse stackoverflow.com/questions/tagged/most-vexing-parse , nhưng bây giờ tôi nghĩ rằng đó là hành vi không xác định chỉ có nghĩa là cả ba trình biên dịch là "đúng".