2011-10-14 35 views

Trả lời

34

Giả sử bạn muốn lấy địa chỉ của các thành viên chức năng size(), sau đó bạn sẽ viết này:

auto address = &demo::size; 

Nhưng nó có thể là rất tốt là địa chỉ của các thành viên dữ liệu size như tốt. Tình hình mơ hồ. Do đó, nó không được phép theo đặc tả ngôn ngữ.

Điều đó không có nghĩa là ủy ban C++ không thể đưa ra giải pháp, nhưng tôi cho rằng không có lợi ích lớn khi làm như vậy. Do đó, tiêu chuẩn chỉ đơn giản là không cho phép nó, để giữ cho mọi thứ đơn giản.

Ngoài ra, sự khác biệt giữa các thành viên dữ liệu và thành viên-chức năng trở nên ít phân biệt thị nếu một tuyên bố hàm thành viên size() như:

typedef void fun_type(); 

struct demo 
{ 
    fun_type size; //It looks like a member-data, but it's a member-function 
}; 

void demo::size() //define the member function 
{ 
    std::cout << "It is crazy!" << std::endl; 
} 

int main() 
{ 
    demo d; 
    d.size(); //call the function! 
} 

Output:

Nó là điên rồ!

Xem các bản demo trực tuyến: http://ideone.com/ZjwyJ

Bây giờ nếu chúng ta có thể thực hiện chức năng thành viên như đã giải thích ở trên, sau đó nó trở nên quá rõ ràng thậm chí bằng mắt thường mà bạn không thể thêm một thành viên khác với cùng tên như:

struct demo 
{ 
    fun_type size; 
    int  size; //error - choose a different name for the member! 
}; 

Đợi Điều đó không hoàn toàn chính xác vì câu chuyện chưa kết thúc. Có một cái gì đó ít rõ ràng hơn tôi cần phải thêm ở đây. Bạn thể thêm nhiều hơn một thành viên với cùng tên:

typedef void fun_type0(); 
typedef void fun_type1(int a); 
typedef void fun_type2(int a, int b); 

struct demo 
{ 
    fun_type0 member; //ok 
    fun_type1 member; //ok 
    fun_type2 member; //ok 
}; 

Đây là mã hoàn toàn hợp lệ, vì mỗi thành viên là một chức năng của khác nhau loại, vì vậy bạn có thể xác định chúng như:

void demo::member() 
{ 
    std::cout << "member()" << std::endl; 
} 
void demo::member(int a) 
{ 
    std::cout << "member(" << a << ")" << std::endl; 
} 
void demo::member(int a, int b) 
{ 
    std::cout << "member(" << a << ", "<< b << ")" << std::endl; 
} 

mã kiểm tra:

int main() 
{ 
    demo d; 
    d.member(); 
    d.member(10); 
    d.member(200,300); 
} 

Output:

member() 
member(10) 
member(200, 300) 

Online Demo: http://ideone.com/OM97Q


Kết luận ...

Bạn có thể thêm các thành viên với cùng một tên, miễn là họ chức năng của khác nhau loại.Đây là được bật bởi một tính năng được gọi là thành viên-chức năng-quá tải (hoặc quá tải hàm đơn giản) .

1. Thật không may, ngôn ngữ không cung cấp tính năng tương tự, nói thành phần dữ liệu quá tải, cho dữ liệu thành viên, không làm ngôn ngữ quá tải thành viên (cho phép thành viên dữ liệu và thành viên chức năng có cùng tên — trường hợp trong câu hỏi).

Vì vậy, ở đây một câu hỏi tự nhiên nảy sinh: chúng không gây ra sự cố mơ hồ ? Có, họ làm. Nhưng điểm cần lưu ý là ủy ban C++ đã đưa ra một giải pháp để giải quyết vấn đề mơ hồ này, bởi vì họ thấy một sự gia tăng lớn trong việc làm như vậy, (trong trường hợp quá tải hàm).

Nhưng trường hợp trong câu hỏi vẫn còn mơ hồ, vì ủy ban đã không đưa ra giải pháp, vì họ không thấy bất kỳ lợi thế lớn nào khi làm như vậy (như đã nói trước đây). Ngoài ra, khi tôi nói "Ủy ban C++ đã đưa ra giải pháp", tôi KHÔNG có nghĩa là giải pháp đã được tiêu chuẩn hoá, tôi chỉ có nghĩa là họ biết cách trình biên dịch có thể giải quyết nó và được.

+0

Sự mơ hồ không thực sự là câu trả lời. Nó khác biệt như thế nào nếu 'demo :: size' là một hàm bị quá tải? – tenfour

+1

@tenfour: Bạn đã bỏ lỡ điểm hoàn toàn. Sự mơ hồ * là * ở đó cho các chức năng quá tải, nhưng vấn đề là ủy ban C++ đã đưa ra một giải pháp để giải quyết vấn đề mơ hồ này, bởi vì họ đã đạt được một lợi ích to lớn khi làm như vậy. Nhưng trường hợp này trong câu hỏi vẫn còn mơ hồ, vì ủy ban đã không đưa ra một giải pháp. Và khi tôi nói * "Ủy ban C++ đưa ra giải pháp" *, tôi KHÔNG có nghĩa là giải pháp đã được chuẩn hóa, tôi chỉ có nghĩa là họ biết cách trình biên dịch có thể giải quyết nó và giải pháp phức tạp như thế nào. – Nawaz

+0

Tôi nhận được điểm, nhưng có vẻ tương tự như [câu hỏi này] (http://stackoverflow.com/questions/4331837/why-cant-functions-be-overloaded-by-return-type) trong đó câu trả lời có vẻ là sự mơ hồ, nhưng lý do cụ thể hơn là ủy ban muốn thực hiện các cuộc gọi hàm không phụ thuộc vào ngữ cảnh bên ngoài. Tôi tự hỏi nếu có một câu trả lời tương tự chi tiết hơn cho câu hỏi này. (hoặc có lẽ đây là câu trả lời?) – tenfour

6

vì nếu bạn sử dụng size trong lớp của bạn ở đâu đó thì trình biên dịch không biết phải làm gì. Nó có thể là thành viên int-data hoặc nó có thể là con trỏ hàm. Vì vậy, các trình biên dịch không có khả năng để tách cả hai loại

6

Như một ví dụ (Không có lẽ là tốt nhất nhưng nó có thể giải thích nó bằng mắt):

class Size { 
     std::size_t size_; 
    public: 
     Size(std::size_t s = std::size_t()) : size_(s){} 
     std::size_t operator()() const { 
      return size_; 
     } 
     void operator()(std::size_t s) { 
      size_ = s; 
     }   
}; 

class Demo { 
    public: 
     Size size; 
}; 

int main() { 
    Demo d; 
    d.size(10); 
    std::size_t size = d.size(); 
    return 0; 
} 

Về cơ bản các biến có thể là callable là tốt. Vì vậy, không có cách nào cho trình biên dịch biết ý định của bạn. Tất nhiên điều này được xác định bởi ngôn ngữ mà không thể có cùng tên với số nhận dạng trong cùng phạm vi.

+0

Ví dụ tuyệt vời. – UncleZeiv

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