欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 资讯 > 如何实现接口继承与实现继承的区别?C++

如何实现接口继承与实现继承的区别?C++

2024/12/22 0:20:46 来源:https://blog.csdn.net/weixin_73931631/article/details/144491030  浏览:    关键词:如何实现接口继承与实现继承的区别?C++

1. 接口继承(Interface Inheritance)

接口继承指的是派生类从基类继承一组仅有声明没有实现的函数(纯虚函数),这些函数定义了接口(契约),而不包含具体的实现细节。接口继承的目的是为派生类提供一个统一的接口约定,所有派生类必须提供这些接口函数的具体实现。

特点
  • 纯虚函数:接口继承通常通过在基类中声明纯虚函数来实现。纯虚函数没有函数体,派生类必须提供具体的实现。
  • 没有数据成员:接口类通常不包含任何成员变量,只定义接口方法。
  • 无法实例化:接口类不能直接创建对象,因为它包含纯虚函数,只有通过派生类才能实例化。
  • 派生类要求实现所有纯虚函数:派生类如果继承了接口类,必须实现接口类中所有的纯虚函数。
例子
#include <iostream>// 接口类:只声明接口方法,没有实现
class IShape {
public:virtual void draw() = 0;  // 纯虚函数virtual double area() = 0; // 纯虚函数virtual ~IShape() {}  // 虚析构函数,防止派生类对象销毁时内存泄漏
};// 派生类:实现接口中的纯虚函数
class Circle : public IShape {
public:Circle(double radius) : radius_(radius) {}void draw() override {
        std::cout << "Drawing Circle\n";}double area() override {return 3.14 * radius_ * radius_;}private:double radius_;
};int main() {
    IShape* shape = new Circle(10);
    shape->draw();
    std::cout << "Area: " << shape->area() << std::endl;delete shape;return 0;
}

在上面的例子中,IShape 是一个接口类,它定义了两个纯虚函数 draw()area()Circle 类继承自 IShape,并实现了这两个函数。因此,Circle 类提供了具体的实现,而 IShape 类只是一个接口。

2. 实现继承(Implementation Inheritance)

实现继承指的是派生类从基类继承功能实现,基类提供了具体的成员函数实现,派生类可以直接使用这些实现,或者重写这些实现。实现继承的目的是通过继承基类的实现来复用代码。

特点
  • 成员函数实现:基类提供了具体的成员函数实现,派生类可以直接使用这些实现,也可以选择重写基类的成员函数。
  • 可以包含数据成员:与接口类不同,实现继承的基类通常包含数据成员(变量)和成员函数的实现。
  • 可以实例化:基类提供了实现,派生类可以实例化基类的对象,或者通过派生类实例化。
  • 继承代码复用:实现继承允许派生类直接复用基类的实现,从而避免代码重复。
例子
#include <iostream>// 基类:包含具体的实现
class Shape {
public:Shape(double width, double height) : width_(width), height_(height) {}// 成员函数实现void draw() {
        std::cout << "Drawing Shape\n";}double area() {return width_ * height_;}private:double width_;double height_;
};// 派生类:可以继承基类的实现或重写基类的实现
class Rectangle : public Shape {
public:Rectangle(double width, double height) : Shape(width, height) {}// 可以选择不重写基类的函数,直接使用基类的实现
};int main() {
    Shape* shape = new Rectangle(5, 10);
    shape->draw();
    std::cout << "Area: " << shape->area() << std::endl;delete shape;return 0;
}

在这个例子中,Shape 类提供了一个默认的实现,Rectangle 类继承自 Shape,并直接使用 Shape 类中定义的 draw()area() 函数。Rectangle 类没有修改这些函数,因此它可以直接复用 Shape 类中的实现。

3. 接口继承与实现继承的区别

  • 目的
    • 接口继承:定义了一个规范或合同,派生类必须提供具体实现。接口继承注重的是行为,即方法的定义而不是实现。
    • 实现继承:基类提供具体实现,派生类可以直接继承并使用这些实现,或根据需要进行修改。实现继承注重的是复用代码,派生类可以继承基类的功能。
  • 类的设计
    • 接口继承:通常用于定义统一的行为接口,派生类必须实现接口中的所有方法。接口类通常不含成员变量,只定义方法。
    • 实现继承:用于复用代码,派生类继承了基类的具体实现和成员变量,能够直接使用或修改这些实现。
  • 是否提供实现
    • 接口继承:接口类不提供实现,派生类必须提供自己的实现。
    • 实现继承:基类提供具体的实现,派生类可以直接使用,或者修改这些实现。
  • 多重继承
    • 接口继承:C++ 支持多重继承,多个接口可以被实现类同时继承,这通常用于混合多种行为。
    • 实现继承:C++ 也支持多重继承,但如果不同的基类中有相同的方法实现,可能会出现方法冲突,导致“二义性”(ambiguity)。

4. C++ 中的接口继承和实现继承结合使用

在 C++ 中,接口继承和实现继承经常结合使用,以提供强大的灵活性。一个常见的模式是,基类提供接口(通过纯虚函数)并实现一些功能,而派生类则实现其他的功能或重写基类的某些方法。

例子
#include <iostream>class IShape {
public:virtual void draw() = 0;  // 纯虚函数virtual double area() = 0;virtual ~IShape() {}
};class Shape : public IShape {
public:Shape(double width, double height) : width_(width), height_(height) {}void draw() override {
        std::cout << "Drawing Shape\n";}double area() override {return width_ * height_;}private:double width_;double height_;
};class Rectangle : public Shape {
public:Rectangle(double width, double height) : Shape(width, height) {}// 可以重写基类的方法void draw() override {
        std::cout << "Drawing Rectangle\n";}
};int main() {
    IShape* shape = new Rectangle(5, 10);
    shape->draw();
    std::cout << "Area: " << shape->area() << std::endl;delete shape;return 0;
}

在这个例子中,IShape 是接口类,Shape 是实现类,Rectangle 则是从 Shape 类继承并重写了 draw() 方法。通过这种方式,我们既可以使用接口定义统一的行为,也可以在实现类中提供默认行为,并允许派生类进一步修改。

总结

  • 接口继承:注重行为的定义,没有实现,派生类必须提供实现。
  • 实现继承:基类提供实现,派生类可以复用或修改这些实现。
  • 应用场景:接口继承适用于需要保证一组类具有相同功能接口的场景,常用于多态设计;实现继承适用于需要共享代码或功能的场景,常用于避免代码重复。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com