C++中的虚函数和纯虚函数

 

在C++中,虚函数和纯虚函数都有助于实现多态性,但它们之间有几个重要的区别。总结来说,虚函数允许派生类选择性的重写某个函数,而纯虚函数则是规定了所有派生类都需要提供的某种行为

 

一、虚函数 (Virtual Function)

1. 定义:

当你在基类中使用 virtual 关键字声明一个成员函数时,你就创建了一个虚函数。这意味着即使通过基类指针引用调用了该函数,实际执行的可能是派生类中重写的版本。


2. 特点:

(1) 可选重写: 派生类可以选择是否要重写虚函数。
(2) 默认实现: 基类可以提供虚函数的默认实现,但如果派生类提供了新的实现,则优先采用派生类的实现。
(3) 动态绑定: 使用基类指针或引用来访问虚函数时,会在运行时决定调用哪个具体的函数实现。


3. 例子

class Base {
public:
    virtual void display() {
        std::cout << "Display from Base" << std::endl;
    }
};

class Derived : public Base {
public:
    void display() override {
        std::cout << "Display from Derived" << std::endl;
    }
};

在这个例子中,如果你有一个 Base* ptr = new Derived() ,然后调用 ptr->display(),输出将是 "Display from Derived",这是因为发生了动态绑定。


二、纯虚函数 (Pure Virtual Function)

1. 定义:

纯虚函数是没有实现的虚函数,通常在其声明末尾添加 "= 0" 来表示。含有至少一个纯虚函数的类被视为抽象类,不能直接实例化。


2. 特点:

(1) 无默认实现: 抽象类自身不提供纯虚函数的具体实现,因此必须依赖派生类来完成。
(2) 强制重写: 所有的派生类都必须提供纯虚函数的具体实现,除非这些派生类也被标记为抽象类。
(3) 确保一致性: 提供了一种接口规范,使得所有派生类都能遵循一致的行为模式。


3. 例子

class AbstractBase {
public:
    virtual void pureFunction() = 0; // Pure virtual function

    virtual void optionalOverrideableFunction() {} // Optional to be overridden
};

class ConcreteDerived : public AbstractBase {
public:
    void pureFunction() override {
        std::cout << "Implemented pure function in derived class" << std::endl;
    }
};

这里,AbstractBase 是一个抽象类,因为你不能 new AbstractBase() 创建对象。然而,你可以创建 ConcreteDerived 的实例,前提是实现了所有的纯虚函数。


三、Java中的接口和C++中的抽象类的区别

Java中的接口(interface)和C++中的纯虚函数构成的抽象类有一些关键的不同。


1. 定义方式:

Java接口: 使用 interface 关键字定义,并且默认所有方法都是公开的抽象方法不需要显式指定 public abstract 。此外,默认情况下,接口内的变量也是 public static final 的常量

C++抽象类: 使用 virtual 关键字标记至少一个纯虚函数即可成为抽象类。这样的类无法被实例化,但它可以包含已经实现的具体方法和其他成员变量。


2. 继承规则:

Java接口: 支持多重继承。这意味着一个类可以通过实现多个接口获得多种能力。

C++抽象类: 只支持单一继承。然而,由于C++允许多重继承(尽管需要谨慎使用),你可以让一个类同时继承自多个基类,其中一个可能是抽象类。


3. 构造函数的存在与否:

Java接口: 不能有构造函数,因为它只是一个契约或规范,而不具备状态。

C++抽象类: 可以有构造函数,用于初始化其自身的成员变量或其他必要的工作。


4. 访问控制:

Java接口: 成员默认是公有的(public),并且不可更改

C++抽象类: 提供更灵活的访问控制选项 (private, protected, public),可以根据需求调整各个成员的可见性和可用性。


5. 总结

虽然两者都可以用来定义一种“模板”式的类,但它们各自的语言背景决定了它们有不同的特点和适用场景。Java倾向于简洁和明确的设计哲学,而C++提供了更多的灵活性但也带来了更高的复杂度。

 

posted on 2024-12-11 20:42  Hello-World3  阅读(17)  评论(0编辑  收藏  举报

导航