2012-10-03 41 views
11

Tôi quá tải một toán tử hai lần với cùng một danh sách tham số. nhưng với loại trả lại khác:Toán tử quá tải C++ hai lần, một tham chiếu không tham chiếu const và tham chiếu const khác, ưu tiên là gì?

T& operator()(par_list){blablabla}  
const T& operator()(par_list){blablabla} 

Vì vậy, khi tôi gọi toán tử(), chức năng nào sẽ được gọi dựa trên sở thích hoặc tình huống nào? Tôi biết rằng nếu tôi gọi() theo hàm const nó phải là const T & một.

Tôi chỉ tò mò về cách C++ đối phó với tình huống như vậy và cách hoạt động của tùy chọn mặc định.

Cảm ơn

+1

Thuật ngữ này là * quá tải *, và không. – chris

+2

C++ Không cho phép quá tải theo kiểu trả về. Người ta có thể đi vào những gì nó có thể/nên làm, nhưng nó sẽ không thành vấn đề. Một mẹo là làm cho phương thức const khi kiểu trả về là const, vì nó có thể bị quá tải. Bộ nhớ của tôi là phương pháp const được ưa thích, với không được gọi là const gọi const sẽ không hợp pháp. – Joe

Trả lời

21

Các chức năng này không quá tải lẫn nhau; chúng có cùng chữ ký, và do đó cố gắng xác định lại chức năng tương tự, đó là một lỗi. Kiểu trả về không phải là một phần của chữ ký của hàm. Để quá tải một hàm, bạn phải khai báo một hàm thứ hai có cùng tên, nhưng các tham số khác nhau hoặc const/volatile vòng loại - nghĩa là, các vòng loại trên hàm, không phải kiểu trả về.

(Chúng cũng không ghi đè lên nhau; ghi đè là những lớp dẫn xuất làm gì cho các hàm ảo của lớp cơ sở).

Thông thường, hãy xác định const và không quá const quá tải của chức năng thành viên; sự quá tải const phải khai báo hàm const, không chỉ là kiểu trả về:

T& operator()(par_list){blablabla} 
const T& operator()(par_list) const {blablabla} 
           ^^^^^ 

Bây giờ là người đầu tiên sẽ được gọi nếu bạn áp dụng () đến một đối tượng phi const, và lần thứ hai vào một đối tượng const. Ví dụ:

Thingy nc; 
Thingy const c; 

nc(); // calls the first (non-const) overload 
c(); // calls the second (const) overload 
+0

@ DavidRodríguez-dribeas: OK, tôi đã không nhận ra "chữ ký" bao gồm kiểu trả về. Có một thuật ngữ chính thức cho "các bit xác định quá tải để chọn"? –

+0

@ DavidRodríguez-dribeas Có lẽ bạn có thể làm rõ điều này vì nó dường như đã thay đổi kể từ C++ 03. '§1.3.18' dường như đề cập đến các hàm mẫu. Nhưng các mục nhập cho các chức năng không phải mẫu (miễn phí hoặc thành viên) không đề cập đến các giá trị trả về. Không làm các mục nhập cho các chuyên ngành chức năng mẫu. – juanchopanza

+0

@juanchopanza: Bạn nói đúng, xóa nhận xét. Mike, một reread cẩn thận của tiêu chuẩn chỉ ra rằng đối với các mẫu chức năng (như Juancho đề cập) kiểu trả về là một phần của chữ ký. Đối với các hàm thông thường, chữ ký không bao gồm kiểu trả về. C++ 03 có chú thích: * Chữ ký chức năng không bao gồm kiểu trả về, vì nó không tham gia vào quá trình phân giải quá tải. * Xin lỗi vì đã giới thiệu nhầm lẫn với câu trả lời :) –

3

Bạn không thể quá tải hàm/phương pháp dựa trên kiểu trả về. Tôi mong đợi trình biên dịch sẽ đưa ra một lỗi ở đây. Những gì bạn có thể làm là xác định các phương pháp chính nó như là một phương pháp const, sử dụng

const T& operator()(par_list) const {blahblah} 

Các const vòng loại không chỉ có nghĩa là điều này có thể được gọi vào một máy thu const, nhưng nó cũng được sử dụng trong việc giải quyết tình trạng quá tải. Điều này xảy ra vì nó ảnh hưởng đến tham số ngụ ý *this được truyền cho phương thức; phương pháp const sử dụng một vòng loại const trên *this và các vòng loại const được tính đến trong quá trình phân giải quá tải.

1

Cách bạn xác định toán tử của mình, không cách nào trình biên dịch có thể quyết định toán tử nào cần gọi. Quá tải các hàm (và toán tử) chỉ có thể được thực hiện trên kiểu đối số, không bao giờ thuộc kiểu trả về. Và trên thực tế, bạn sẽ gặp lỗi khi biên dịch ngay sau khi bạn định nghĩa phần thứ hai, trình biên dịch xem xét rằng bạn đang xác định lại cùng một hàm/toán tử.

Tuy nhiên, sau đây là phổ biến (và có lẽ những gì bạn có):

T& operator()(par_list){blablabla} 
const T& operator()(par_list) const {blablabla} 

bổ sung "const" Đây sau khi danh sách đối số tồn tại bởi vì bạn đang định nghĩa hàm thành viên và hàm thành viên không tĩnh có một tiềm ẩn đối số ẩn: con trỏ "this" đối với cá thể của lớp. Từ khóa "const" có chỉ ra nếu con trỏ ẩn này là một cá thể const hay không.Đối số này tham gia vào độ phân giải quá tải và trong trường hợp này trình biên dịch sử dụng để chọn phiên bản của toán tử để sử dụng.

Vì vậy:

class A { 
    T& operator()() { ... } 
    const T& operator()() const { .... } 
}; 

A a; 
const A& ca(a); 
a(); -> returns a T& 
ca(); -> returns a const T& 
Các vấn đề liên quan