2013-09-27 145 views
13

Đây là mã ...Tôi có thể gọi một phương thức với các đối số được yêu cầu trong C++. Làm thế nào mà?

#include "stdafx.h" 
#include<iostream> 
using namespace std; 

class Base 
{ 
public: 
    virtual void Display(bool b = false) 
    { 
     cout<<"Base"<<"\t"<<b<<endl; 
    } 
}; 

class Derived : public Base 
{ 
public: 
    virtual void Display(bool b) override 
    { 
     cout<<"Derived"<<"\t"<<b<<endl; 
    } 
}; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    Base* bp = new Base(); 
    Derived* dp = new Derived(); 
    bp->Display(); 
    dp->Display(true); 
    bp = new Derived(); 
    bp->Display(); 
    cout<<"Done"<<endl; 
    return 0; 
} 

Khi Display() phương pháp gọi là lần thứ hai sử dụng bp, đáng ngạc nhiên nó nhấn phương pháp này trong Derived lớp. trong lớp Derived Tôi không chỉ định đối số mặc định. Nhưng nó đã lấy đối số lớp cơ sở mặc định. Làm sao?

+0

Tôi đoán bạn có nghĩa là lần thứ ba (lần cuối cùng trong mã của bạn). – john

+0

Có. Tôi cập nhật câu hỏi ngay bây giờ. Cảm ơn. –

+0

Mang lại những kỷ niệm trở lại: http://www.gotw.ca/gotw/005.htm. –

Trả lời

21

Điều này làm ngạc nhiên một vài người, nhưng đối số mặc định là (hoặc đối số là, nếu bạn đã chỉ định nhiều hơn một) dựa trên loại tĩnh (loại con trỏ được khai báo để trỏ) không phải kiểu động (loại đối tượng mà nó hiện đang xảy ra điểm).

Như vậy, kể từ khi bạn đang sử dụng Base *bp, các đối số mặc định tuyên bố trong Base được sử dụng, bất kể bp xảy ra để được trỏ đến một Base hoặc một Derived.

Trong trường hợp bạn quan tâm lý do tại sao điều này là: ít nhất là trong các đối số mặc định thực hiện điển hình thực sự được xử lý hoàn toàn tại thời gian biên dịch. Trình biên dịch thấy rằng bạn đã gọi một Display mà không cung cấp một đối số và rằng Display có một đối số với một giá trị mặc định. Do đó, khi tạo mã cho cuộc gọi đó, mã được tạo để chuyển giá trị mặc định đã được chỉ định. Vào thời điểm đó, nó thậm chí không có cách nào đoán được liệu con trỏ có thể trỏ đến một số kiểu dẫn xuất khi cuộc gọi diễn ra hay không, vì vậy tất cả những gì nó có thể làm là tạo mã dựa trên kiểu tĩnh. Mặc dù nó không phải là trường hợp ở đây, khi nó tạo ra mã để thực hiện cuộc gọi, thậm chí nó có thể hoạt động trên một lớp dẫn xuất chưa được thiết kế hoặc viết, vì vậy sử dụng một giá trị được chỉ định trong lớp dẫn xuất đó sẽ không thể.

+0

Điều tốt cần lưu ý – Cramer

+0

Nếu tôi nhớ lại C++, nếu bạn thêm từ khóa 'virtual', chương trình sẽ chạy hàm từ kiểu đối tượng hiện tại. đúng? –

+0

@STTLCU: Nó đã làm điều đó. –