C++ 抽象类和接口 详解

请添加图片描述

  • 🙋‍♂️ 作者:海码007
  • 📜 专栏:C++专栏
  • 💥 标题:C++ 抽象类和接口 详解
  • ❣️ 寄语:书到用时方恨少,事非经过不知难!
  • 🎈 最后:文章作者技术和水平有限,如果文中出现错误,希望大家能指正

0 引言

随着编程的深入,总是会听到不少抽象类,接口等词汇。但是其实很多有都在混淆概念,甚至是乱用这些定义。接下来就和我一起探讨一下C++中的抽象类和接口的区别,以及拓展一下 C++ 和 Java 的区别。

1 抽象类

在C++中,抽象类(Abstract Class)是包含至少一个纯虚函数的类。抽象类不能被实例化,只能被用作其他类的基类。纯虚函数是一种在基类中声明但没有提供实际实现的虚函数,它的存在要求任何继承自这个基类的派生类都必须提供实际的实现(如果不实现,那基类仍然是抽象类)。这样的设计允许抽象类提供一个接口,而具体的实现则由派生类完成。

在C++中,定义一个抽象类的典型方式如下:

class AbstractClass {
public:
    // 纯虚函数,使得AbstractClass成为抽象类
    virtual void pureVirtualFunction() = 0;

	// 虚析构函数(防止派生类析构时,不调用派生类的析构函数)
	virtual ~AbstractClass() {}

    // 普通成员函数
    void concreteFunction() {
        // 可以包含具体实现
        // 但通常抽象类中也包含一些纯虚函数,以强制派生类提供实现
    }

    // 普通成员变量
    int data;
};

在这个例子中,pureVirtualFunction是一个纯虚函数,因此AbstractClass就成为了抽象类。由于抽象类不能被实例化,你不能创建AbstractClass的对象。它主要用于作为其他类的基类,要求派生类必须提供纯虚函数的实际实现。

具体的派生类可以这样实现:

class ConcreteClass : public AbstractClass {
public:
    // 实现纯虚函数
    void pureVirtualFunction() override {
        // 具体的实现
    }
};

注意,在派生类中必须提供对抽象类中纯虚函数的实现,否则派生类也会变成抽象类,无法被实例化。

2 接口

在C++中接口就是一种特殊的抽象类,接口中只包括纯虚函数。

在C++中,与一些其他编程语言(如Java和C#)不同,C++没有显式的接口关键字。然而,C++中可以通过抽象类和纯虚函数来实现接口的概念。

在C++中,接口通常是通过抽象类来定义的,该抽象类包含纯虚函数(没有实现),而派生类则负责提供这些纯虚函数的具体实现。这种方式类似于其他语言中的接口定义。

下面是一个使用抽象类和纯虚函数实现接口的简单示例:

#include <iostream>

// 定义接口(抽象类)
class Interface {
public:
    // 纯虚函数,相当于接口中的方法声明
    virtual void doSomething() = 0;
};

// 不能在接口中包含普通成员函数
// 下面的代码会导致编译错误
/*
class Interface {
public:
    virtual void doSomething() = 0;
    void commonFunction() {
        std::cout << "Common function in Interface." << std::endl;
    }
};
*/

// 实现接口的具体类
class ConcreteClass : public Interface {
public:
    // 提供接口中纯虚函数的具体实现
    void doSomething() override {
        std::cout << "Doing something in ConcreteClass." << std::endl;
    }
};

int main() {
    // 通过接口指针调用实现类的方法
    Interface* obj = new ConcreteClass();
    obj->doSomething();

    delete obj;
    return 0;
}

2.1 Java与C++接口的区别

Java和C++在接口(interface)方面存在一些显著的区别。了解这些区别对于使用这两种语言进行编程是很重要的。以下是主要的区别点:

  1. 定义和用途:

    • Java接口:Java中的接口是一个完全抽象的类,只能包含抽象方法和常量。接口用于声明一组方法,然后由其他类实现。Java接口是实现多继承的一种方式。
    • C++接口:C++没有内置的接口关键字,但可以通过创建纯虚函数(pure virtual functions)的抽象类来模拟接口。这些类不能被实例化,只能被其他类继承。
  2. 实现方法:

    • Java:在Java中,类可以实现多个接口。使用interface关键字来实现接口,并且必须实现接口中的所有方法。
    • C++:C++中的类通过继承抽象类来实现接口,并且必须实现所有的纯虚函数。C++支持多重继承,因此一个类可以继承多个抽象类。
  3. 默认方法:

    • Java:从Java 8开始,接口可以包含默认方法(default methods)。这些方法不是抽象的,可以有自己的实现。这允许在不影响实现该接口的类的情况下添加新功能。
    • C++:C++的抽象类可以包含已经实现的成员函数,这在某种程度上类似于Java的默认方法。
  4. 属性:

    • Java:Java接口中可以声明常量,但不能包含实例字段。所有定义在接口中的变量默认都是public static final的。
    • C++:C++中的抽象类可以包含成员变量和常量。
  5. 多重继承和菱形问题(Diamond Problem):

    • Java:由于Java不支持从多个类继承,因此使用接口来实现多重继承。Java接口不会导致菱形问题,因为它们不具备实现继承。
    • C++:C++支持从多个类继承,但这可能导致菱形问题。当两个父类都继承自同一个祖先类时,子类可能会从每个父类继承相同的祖先类的两个副本。

这些差异反映了Java和C++设计哲学的不同:Java更注重简洁和安全,而C++提供了更高的灵活性和控制权,但也带来了更复杂的语言特性和潜在的错误风险。

// 定义一个接口
interface Vehicle {
    void drive();
    int getNumberOfWheels();
}

// 一个类实现接口
class Car implements Vehicle {
    public void drive() {
        // 实现drive方法的具体逻辑
    }

    public int getNumberOfWheels() {
        // 返回轮子数量
        return 4;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值