2010-09-30 50 views
6

Với đoạn mã sau,C++ ảo Const Chức năng

class Base 
{ 
public: 
    virtual void eval() const 
    { 
     std::cout<<"Base Const Eval\n"; 
    } 
}; 

class Derived:public Base 
{ 
public: 
    void eval() 
    { 
     std::cout<<"Derived Non-Const Eval\n"; 
    } 
}; 

int main() 
{ 

    Derived d; 
    Base* pB=&d; 

    pB->eval(); //This will call the Base eval() 

    return 0; 
} 

Tại sao pB-> eval() sẽ gọi cơ sở :: eval()?

Cảm ơn bạn

Trả lời

6

Điều này là do người ta tuyên bố const và người kia thì không. Một hàm đang bị ẩn bởi hàm kia. Hàm trong Derived đang ẩn một trong Base bởi vì chúng có cùng tên trong khi chúng không có cùng chức năng.

Trình biên dịch của tôi đưa ra cảnh báo ở đây, phải không?

+0

Tò mò: trình biên dịch gì? Tùy chọn cảnh báo nào? – Arun

+0

Nếu bạn bật cảnh báo trên hầu hết các trình biên dịch sẽ. –

8

Trong lớp Derived của bạn, nguyên mẫu cho eval không khớp với mẫu cho hàm ảo trong Base. Vì vậy, nó sẽ không ghi đè lên chức năng ảo.

Base::eval() const; 
Derived::eval(); //No const. 

Nếu bạn thêm const cho Derived::eval(), bạn sẽ nhận được hành vi ảo.

2

const là một phần của chữ ký chức năng. Để ghi đè lên một hàm, ghi đè phải có cùng chữ ký giống với phiên bản cơ sở - trong trường hợp này nó không có.

Hãy xem xét mã gọi điện thoại không cần biết bất kỳ điều gì về số Derived - nó đang gọi hàm const trên Base. Bạn sẽ không mong đợi rằng cuộc gọi để gió lên trong một chức năng không const có thể thay đổi công cụ về lớp học.

5

$ 10,3/2- "Nếu một hàm thành viên ảo vf được khai báo trong một cơ sở lớp và trong một lớp Derived, có nguồn gốc trực tiếp hoặc gián tiếp từ cơ sở, một thành viên chức năng vf có cùng tên, tham số-loại-danh sách (8.3.5), cv-qualification và bộ lọc (hoặc không giống nhau) làm cơ sở :: vf là tuyên bố, sau đó Derived :: vf cũng là ảo (có hay không) như vậy là đã tuyên bố) và nó ghi đè111 Cơ sở :: vf. "

111) Một chức năng có cùng tên nhưng một danh sách khác nhau tham số (khoản 13) như một hàm ảo là không nhất thiết ảo và không ghi đè. Việc sử dụng số thông số ảo trong tuyên bố hàm số ghi đè là hợp pháp nhưng dự phòng (có ngữ nghĩa trống). Kiểm soát truy cập (Điều 11) không phải là được xem xét trong việc xác định trọng số.

Ngoài ra, lưu ý rằng nó không nói về các đặc điểm truy cập. Vì vậy, các lớp cơ sở và các bộ định danh truy cập lớp dẫn xuất cho hàm được ghi đè có thể khác nhau

Điều này có nghĩa là Derived :: eval không ghi đè Base :: eval.

8

Bạn có thể dịch trong tâm trí của bạn:

virtual void Base::eval() const; 
void Derived::eval() ; 

để

void eval(const Base *this, size_t vtable_offset); 
void eval(Derived *this); 

và xem qua sự kiểm tra như thế nào ít thứ hai phù hợp với chữ ký của người đầu tiên.

+0

+1: Mô hình tinh thần tốt. (Bạn có thể muốn đánh dấu mã của mình.) – Arun

2

Trong C++ 0x, tình hình có thể phát hiện tại thời gian biên dịch bằng cách sử dụng các từ khóa base_checkoverride. Excerpt from wikipedia:

Các [[base_check]] thuộc tính trên một lớp/struct có nghĩa là bất cứ ngầm trọng sẽ làm phát sinh một lỗi biên dịch. Giá trị ghi đè bất kỳ phải là được đánh dấu rõ ràng với thuộc tính [[ghi đè]].

lẽ nhiều nhất (không phải là rất chắc chắn về cú pháp):

class Derived [[base_check]] : public Base { 

    virtual void eval [[override]]() { 
     .... 
    } 
}; 
Các vấn đề liên quan