Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Java

Khác biệt hành vi virtual method mặc định giữa C++ và Java

Hành vi mặc định của method về tính virtual (có thể override) khác biệt căn bản giữa C++ và Java.

C++: Non-virtual by default

  • Method mặc định không phải virtual → static binding (compile-time).
  • Muốn dynamic dispatch → phải khai báo explicit virtual.
  • Destructor nên virtual nếu class dùng làm base class.
// C++
class Base {
public:
    void display() { cout << "Base::display\n"; } // NON-VIRTUAL
    virtual void show() { cout << "Base::show\n"; } // VIRTUAL
};

class Derived : public Base {
public:
    void display() { cout << "Derived::display\n"; } // HIDES Base::display
    void show() override { cout << "Derived::show\n"; } // OVERRIDES Base::show
};

int main() {
    Base* ptr = new Derived();
    ptr->display(); // Base::display (static binding - NON-VIRTUAL)
    ptr->show();    // Derived::show (dynamic binding - VIRTUAL)
    delete ptr;
}

Java: Virtual by default

  • Tất cả instance methods mặc định là virtual (dynamic binding).
  • Không có từ khóa virtual.
  • Để làm non-virtual: dùng final, private, static, hoặc constructor.
// Java
class BaseClass {
    public void displayMsg() {          // VIRTUAL by default
        System.out.println("BaseClass displayMsg");
    }
    
    final void cannotOverride() { }     // NON-VIRTUAL (final)
    private void internal() { }         // NON-VIRTUAL (private)
    static void classMethod() { }       // NON-VIRTUAL (static)
}

class DerivedClass extends BaseClass {
    @Override
    public void displayMsg() {          // OVERRIDE
        System.out.println("DerivedClass displayMsg");
    }
    // void cannotOverride() { } // COMPILE ERROR: cannot override final
    // void internal() { }         // OK: private method không visible, không override
    // static void classMethod() { } // HIDING, không override
}

public class Main {
    public static void main(String[] args) {
        BaseClass obj = new DerivedClass();
        obj.displayMsg(); // DerivedClass displayMsg (DYNAMIC BINDING)
    }
}

Bảng so sánh

Đặc điểmC++Java
Instance method mặc địnhNon-virtual (static binding)Virtual (dynamic binding)
Từ khóa bật virtualvirtualMặc định (không cần keyword)
Từ khóa tắt virtualKhông có (chỉ bỏ virtual)final, private, static
DestructorCần virtual cho base classKhông có destructor (finalize() deprecated, dùng try-with-resources/Cleaner)
Static methodNon-virtual (class-level)Non-virtual (class-level, hiding)
Multiple inheritanceCó (virtual inheritance cho diamond)Không (interface default method giải quyết một phần)

Tại sao Java chọn Virtual by default?

  • Thiết kế OOP thuần túy: polymorphism là mặc định, encapsulation hành vi.
  • Tránh lỗi quên virtual dẫn đến sai hành vi (common C++ bug).
  • Interface-based design: tất cả method interface là virtual.
  • JVM tối ưu dynamic dispatch tốt (inline caching, CHA – Class Hierarchy Analysis).

Performance Note

  • C++: Non-virtual = direct call (fastest). Virtual = v-table lookup (1 indirection).
  • Java: Mọi instance call = virtual call. Nhưng JIT compiler thực hiện devirtualization (inline) khi phát hiện chỉ có 1 implementation tại runtime (monomorphic call site).
  • Kết quả: Java virtual call performance ~ C++ non-virtual sau JIT warmup.