Đoạn mã dưới đây gây ra lỗi biên dịch cho tôi. Có ai có thể cho tôi biết tại sao không?
lớp mytype {
public:
giá trị int;
mytype(int a) {
giá trị = a;
}
friend ostream& operator<<(ostream&stream, const mytype& a) {
luồng << a.value;//hoạt động
luồng trở lại;
}
bạn ostringstream& operator<<(ostringstream& stream, const mytype& a) {
luồng << (a.value);//lỗi biên dịch
luồng trở lại;
}
};
sai lầm:
lỗi C2027: sử dụng loại không xác định 'std::basic_ostringstream<_Elem,_Traits,_Alloc>'
Sau khi sửa chữa:
lỗi C2666: 'toán tử <<': 18 tình trạng quá tải có chuyển đổi tương tự
Sửa chữa cuối cùng:
Khai báo hàm tạo là rõ ràng. Hoạt động trên MSVC.
Tôi muốn biết tại sao.
lỗi C2027: sử dụng loại không xác định 'std::basic_ostringstream<_Elem,_Traits,_Alloc>'
你需要#include
得到[i/o]chuỗi
loại.
Về các lỗi khác
Vấn đề tải lại biểu mẫu
ostringstream& operator<<(ostringstream&stream, const mytype& a)
nó có phù hợp không dòng suối
Chính xác. Tại sao tăng tốc chính xác hơn lại là một điều xấu? Theo tiêu chuẩn, §13.3.3/1-2:
một hàm khả thi F1 được xác định là một hàm tốt hơn hàm khả thi F2 khác nếu với tất cả các đối số i, ICSi(F1) không phải là một chuỗi chuyển đổi kém hơn ICSi(F2) …
Nếu có chính xác một hàm khả thi tốt hơn tất cả các hàm khả thi khác thì đó chính là hàm được chọn theo độ phân giải quá tải; nếu không thì cuộc gọi sẽ không được định dạng;
Vậy nếutoán tử<<( ostream &, int )
Và toán tử<<( ostringstream &, mytype const & )
Tất cảluồng << giá trị
của các ứng cử viên, các trận đấu trước đây int
Không có sự chuyển đổi nào cả, nhưng cái sau phù hợp dòng suối
Chính xác. Vì vậy, đối vớitất cảCó thể cho rằng, cả hai đều không "xấu" và cũng không được chọn.
Tuy nhiên, do có lỗ hổng, mãĐúngHiệu quả. Tình trạng quá tải của bạn hoàn toàn không phải là một ứng cử viên, trừ khi bạn thực sự sử dụng loại của mình trong lệnh gọi hàm. Khi bạn khai báo/định nghĩa một người bạn
Trong một khối lớp, nó không đưa nó vào bất kỳ phạm vi không gian tên nào;SẽNó được liên kết với phạm vi lớp, cho phép tìm thấy loại lớp khi nó mô tả một trong các tham số được truyền.
Tiêu chuẩn có điều này để nói về việc khai báo bạn bè, mặc dù nó nằm ở phần khác (14.6.5):
Tuyên bố kết bạn không đưa tên mới vào bất kỳ phạm vi nào…
Vì vậy, MSVC cố gắng tỏ ra thân thiện và chủ động giới thiệu cho bạn bè của bạn về không gian tên kèm theo của nó. Đấu tranh chống lại MSVC.
Tuy nhiên, khi tôi cố gắng thêm một tuyên bố tương đương với "miễn phí" mà MSVC thực hiện, Comeau và GCC đã giải quyết tốt xung đột quá tải dẫn đến - chống lại họ. Hay là vậy? Hóa ra cuộc gọi quá tải xảy ra trong tệp sớm hơn khai báo được đề xuất của tôi. nếu tôi là lớp mytype {
trước khi khai báo di chuyển (việc này yêu cầu khai báo chuyển tiếp kiểu của tôi
), và sau đó cả hai bên sẽ giải quyết sự mơ hồ một cách thích hợp.
Theo §3.3-3.4 của tiêu chuẩn, có vẻ ổn khi sử dụng quá tải trước khi khai báo chúng trong phạm vi không gian tên. Vì vậy, thực sự cả GCC và Comeau đều đúng. Điểm khai báo ngay sau tên đối tượng được khai báo. (Lần cuối tôi kiểm tra, khai báo hàm tự tham chiếu vẫn ổn vẫn gặp sự cố GCC . )ADL gọi một tra cứu không đủ tiêu chuẩn của không gian tên kèm theo tại một điểm trước lớp kèm theo. (3.4.1/8 viên đạn cuối cùng, 3.4.1/9, 3.4.2/2a.) Nếu bạn không được thông báo trước lớp thì đó không phải là ứng cử viên. (7.3.1.2/3) C++ có phải là một ngôn ngữ đẹp không?
Cách giữ các ví dụ đơn giản trên GCC nhưng phá vỡ mã tiếp theo.
bạn ostringstream& operator<<(ostringstream& stream, const mytype& a) {
luồng << (a.value);//lỗi biên dịch
luồng trở lại;
}
};
ostringstream& operator<<(ostringstream&stream, const mytype& a); // <- tại đây
Sau tuyên bố này, sẽ không thể viết int
进入 dòng suối
.
Làm thế nào để thống nhất mọi thứ với ngữ nghĩa khai báo đơn giản hơn.
lớp mytype; // <- tại đây
// và đây:
nội tuyến ostringstream& operator<<(ostringstream& stream, const mytype& a);
lớp mytype {
public:
Sau tuyên bố này, sẽ không thể viết int
进入 dòng suối
...bao gồmlớp mytype {}
tuyên bố kết bạn trong .
Giải pháp thiết thực.
Các lớp luồng phải không thể phân biệt được. Nếu bạn thực sự muốn xác định xem một luồng nhất định có cung cấp một chuỗi trong bộ nhớ hay không (bạn không nên làm như vậy), tốt hơn hết là bạn nên xem bên trong luồng đó suốibuf
đối tượng, gồm có rdbuf()
Trả về, thực sự thực hiện công việc nặng nhọc I/O. Ngay cả khi nó là phổ quát suối
Đồ vật có thể có dòng suối
nếu được chuỗibuf
chức năng.
if ( typeid(stream.rdbuf() ) == typeid( stringbuf * ) ) {
// đây thực sự là một chuỗi chuỗi
} khác {
// không phải là một chuỗi
}
Tôi là một lập trình viên xuất sắc, rất giỏi!