8

Tôi có một lớp học mà trông giống như sau:Rắc rối với const/không const độ phân giải quá tải

class ClassA 
{ 
    public: 
    float Get(int num) const; 
    protected: 
    float& Get(int num); 
} 

Bên ngoài của lớp, tôi gọi là Nhận) chức năng (.

float foo = classAInstance.Get(i); 

Tôi hy vọng điều này để gọi phiên bản nào, nhưng thay vào đó Visual Studio lỗi out:

error C2248: 'ClassA::Get' : cannot access protected member declared in class 'ClassA' 

Khi ý kiến ​​ra tình trạng quá tải bảo vệ và loại bỏ tất cả các tham chiếu đến nó, mã biên dịch.

Tại sao trình biên dịch cố gắng sử dụng thành viên không thể truy cập khi có thể truy cập được? Có cách nào được chấp nhận để buộc trình biên dịch chọn quá tải chính xác không? Có một tham chiếu đến các quy tắc giải quyết cho các chức năng thành viên ở đâu đó không?

Trả lời

7

Đó là sự thật, quá trình phân giải quá tải diễn ra trước khi kiểm tra trợ năng. Mục 13.3 của tiêu chuẩn ([over.match]) nói:

độ phân giải quá tải là một cơ chế cho việc lựa chọn các chức năng tốt nhất để gọi được đưa ra một danh sách các biểu thức có là các đối số của cuộc gọi và một tập hợp các chức năng ứng cử viên mà có thể được gọi dựa trên ngữ cảnh của cuộc gọi. Các tiêu chuẩn lựa chọn cho hàm tốt nhất là số lượng đối số, đối số khớp với tham số kiểu danh sách hàm ứng cử viên như thế nào (đối với các hàm thành viên không tĩnh) đối tượng khớp với tham số đối tượng ẩn, và một số thuộc tính khác của hàm ứng cử viên. [Lưu ý: Chức năng được chọn bởi độ phân giải quá tải không được đảm bảo phù hợp với ngữ cảnh. Các hạn chế khác của , chẳng hạn như khả năng truy cập của hàm, có thể sử dụng nó trong ngữ cảnh gọi là không đúng định dạng. - lưu ý kết thúc]

Khắc phục thông thường là cung cấp cho công chúng và các chức năng được bảo vệ các tên khác nhau.


Lưu ý, đây là hữu ích đôi khi, ví dụ:

class Blah 
{ 
    const std::string& name_ref; 

    Blah(const char*) = delete; 

public: 
    Blah(const std::string& name) : name_ref(name) {} 

    void do_something_with_name_ref() const; 
}; 

std::string s = "Blam"; 
Blah b(s); // ok 

Lưu ý rằng name_ref sẽ chỉ được đọc từ, do đó, nó thích hợp để làm cho nó const. Tuy nhiên, các tham chiếu const có thể liên kết với các thời gian và ràng buộc name_ref với một tham chiếu tạm thời sẽ là một tham chiếu đáng yêu, dẫn đến hành vi không xác định trong do_something_with_name_ref().

Blah c("Kablooey!"); // would be undefined behavior 
        // the constructor overload makes this a compile error 

Quá tải xây dựng tư nhân ngăn cản tạm thời được xây dựng và ràng buộc.

+0

Ví dụ này có vẻ nguy hiểm. Với 'string func();' và một biểu thức của 'Blah b (func())' sẽ biên dịch và vẫn dẫn đến một tham chiếu lơ lửng. Quy tắc của tôi ở đây là: * Không bao giờ * giữ lại các tham số 'const &'.bạn nói gì? –

+0

@MartinBa: Chắc chắn bạn cũng muốn 'Blah (string &&) = delete;' –

+0

Hm. Và câu hỏi sau đó sẽ trở thành nếu 'const char'overload vẫn được yêu cầu. thông số 'char *' có liên kết với phiên bản 'chuỗi const &' hay phiên bản 'string &&' không? :-) –

5

Phân giải quá tải được thực hiện trước và kiểm tra quyền truy cập sau.

Nếu bạn có cả quá tải const và không const, điều này được giải quyết bằng độ chói của đối tượng mà hàm được gọi.

Các vấn đề liên quan