2012-06-17 34 views
37

Giả sử kịch bản này trong Visual C++ 2010:phương pháp phi ảo Overriding

#include <iostream> 
#include <conio.h> 

using namespace std; 

class Base 
{ 
public: 
    int b; 
    void Display() 
    { 
     cout<<"Base: Non-virtual display."<<endl; 
    }; 
    virtual void vDisplay() 
    { 
     cout<<"Base: Virtual display."<<endl; 
    }; 
}; 

class Derived : public Base 
{ 
public: 
    int d; 
    void Display() 
    { 
     cout<<"Derived: Non-virtual display."<<endl; 
    }; 
    virtual void vDisplay() 
    { 
     cout<<"Derived: Virtual display."<<endl; 
    }; 
}; 

int main() 
{ 
    Base ba; 
    Derived de; 

    ba.Display(); 
    ba.vDisplay(); 
    de.Display(); 
    de.vDisplay(); 

    _getch(); 
    return 0; 
}; 

Về mặt lý thuyết, đầu ra của ứng dụng này ít nên là:

  • Base: hiển thị không ảo.
  • Cơ sở: Hiển thị ảo.
  • Cơ sở: Màn hình không phải ảo.
  • Xuất phát: Hiển thị ảo.

vì Phương pháp hiển thị của lớp Cơ sở không phải là phương pháp ảo nên lớp gốc không được ghi đè lên lớp đó. Đúng?

Vấn đề là khi tôi chạy ứng dụng, nó in này:

  • Base: hiển thị không ảo.
  • Cơ sở: Hiển thị ảo.
  • Có nguồn gốc: Hiển thị không phải ảo.
  • Xuất phát: Hiển thị ảo.

Vì vậy, hoặc tôi không hiểu khái niệm về phương pháp ảo hoặc điều gì đó lạ xảy ra trong Visual C++.

Ai đó có thể giúp tôi giải thích?

+0

bạn hoàn toàn sẽ có __Base: Hiển thị không ảo .__ khi thay đổi dòng của bạn thành 'de.Base :: Display()'. –

Trả lời

50

Vâng, bạn hiểu lầm một chút.

Phương thức cùng tên trên lớp dẫn xuất sẽ ẩn phương thức gốc trong trường hợp này. Bạn sẽ tưởng tượng rằng nếu đây không phải là trường hợp, cố gắng tạo ra một phương thức có cùng tên như một phương thức không phải là lớp cơ sở ảo sẽ ném một lỗi. Nó được cho phép và nó không phải là một vấn đề - và nếu bạn gọi phương thức trực tiếp như bạn đã làm, nó sẽ được gọi là tiền phạt.

Nhưng, không phải là ảo, cơ chế tra cứu phương pháp C++ cho phép đa hình sẽ không được sử dụng. Vì vậy, ví dụ nếu bạn tạo một thể hiện của lớp dẫn xuất của bạn nhưng được gọi là phương thức 'Hiển thị' của bạn thông qua một con trỏ đến lớp cơ sở, phương thức của cơ sở sẽ được gọi, trong khi đó 'vDisplay' thì phương thức dẫn xuất sẽ được gọi.

Ví dụ, hãy thử thêm những dòng này:

Base *b = &ba; 
b->Display(); 
b->vDisplay(); 
b = &de; 
b->Display(); 
b->vDisplay(); 

... và quan sát kết quả như mong đợi:

Base: hiển thị không ảo.
Cơ sở: Hiển thị ảo.
Cơ sở: Màn hình không phải ảo.
Có nguồn gốc: Hiển thị ảo.

+0

Hi @ sje397, cảm ơn bạn đã trả lời. Bạn có thể viết một ví dụ gọi phương thức, như bạn đã nói, thông qua một con trỏ đến lớp cơ sở? Cảm ơn bạn! –

+0

@Leif Lazar: đã xong. – sje397

+0

cũng như tôi đã nói, bạn có thể C callNG gọi phương thức cơ sở (không phải ảo) từ cá thể có nguồn gốc, sử dụng cú pháp độ phân giải phạm vi. –

3

Có bạn đã hiểu lầm một chút:

tinh khiết chức năng ảo:

virtual void fun1()=0 -> phải được ghi đè trong lớp có nguồn gốc

chức năng ảo:

virtual void fun2() -> có thể bị ghi đè

chức năng bình thường:

void fun3() -> không ghi đè lên nó

Để đạt được đa hình runtime bạn cần phải ghi đè lên các chức năng ảo trong C++

0

Tôi nghĩ rằng nó có thể là cũng tốt hơn để nhìn vào nó trong bối cảnh liên kết tĩnh và động.

Nếu phương pháp không phải ảo (mặc định trong C++ không giống Java), thì phương thức này liên kết với người gọi của nó tại thời gian biên dịch, không thể biết đối tượng thực sự sẽ được trỏ vào thời gian chạy. Vì vậy, loại biến là tất cả những vấn đề đó là 'Base'.

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