다이아몬드 상속 문제: 파생 클래스가 여러 기본 클래스에서 동시에 동일한 함수를 상속하고 호출할 함수 버전을 결정할 수 없을 때 문제가 발생합니다. 해결 방법: 가상 상속: 함수 호출이 항상 가장 구체적인 기본 클래스 구현을 가리키도록 기본 클래스의 가상 테이블 포인터를 만듭니다. 실제 사례: 실린더 클래스는 Circle 및 Rectangle에서 상속하고, 가상 상속을 사용하여 다이아몬드 상속을 방지하며, 실린더 클래스의 getArea() 함수 구현이 항상 호출되도록 합니다.
C++ 함수 상속 자세한 설명: "다이아몬드 상속" 다루기
Introduction
함수 상속은 파생 클래스가 기본 클래스의 함수에 액세스하고 재사용할 수 있도록 하는 C++의 강력한 기능입니다. 그러나 여러 기본 클래스가 동일한 기능을 갖는 경우 "다이아몬드 상속"이라는 문제가 발생할 수 있습니다. 이 기사에서는 다이아몬드 상속과 그 솔루션에 대해 논의하고 실제 사례를 제공합니다.
다이아몬드 상속
다이아몬드 상속은 파생 클래스가 둘 이상의 기본 클래스에서 동시에 동일한 함수를 상속할 때 발생합니다. 이로 인해 파생 클래스에서 어떤 함수 버전이 호출되었는지 확인할 수 없게 됩니다.
class Base1 { public: void print() { std::cout << "Base1 print" << std::endl; } }; class Base2 { public: void print() { std::cout << "Base2 print" << std::endl; } }; class Derived : public Base1, public Base2 { public: void print() { // 调用哪个基类的 print() 函数? } };
위의 예에서 Derived
클래스는 Base1
및 Base2
에서 상속되며 두 기본 클래스 모두 동일한 print()를 갖습니다.
함수. Derived::print()
를 호출할 때 Base1::print()
또는 Base2::print()
가 호출되었는지 확인할 수 없습니다. . Derived
类从 Base1
和 Base2
继承,这两个基类都有相同的 print()
函数。当调用 Derived::print()
时,无法确定是否调用 Base1::print()
或 Base2::print()
。
避免钻石继承
避免钻石继承的一个常见解决方案是使用虚继承。虚继承会创建基类的虚表指针,而不是复制基类的对象。这确保了针对派生类的函数调用总是指向最具体的基类实现。
class Base1 { public: virtual void print() { std::cout << "Base1 print" << std::endl; } }; class Base2 { public: virtual void print() { std::cout << "Base2 print" << std::endl; } }; class Derived : public virtual Base1, public virtual Base2 { public: void print() override { std::cout << "Derived print" << std::endl; } };
在上面的示例中,Base1
和 Base2
使用了虚继承。这确保了 Derived::print()
将始终调用 Derived
类的实现。
实战案例
考虑一个计算图形面积的示例。我们有一个基类 Shape
,它定义了计算面积的 getArea()
函数。我们还有两个派生类 Circle
和 Rectangle
,它们提供形状特定的面积计算。
class Shape { public: virtual double getArea() = 0; }; class Circle : public Shape { public: Circle(double radius) : _radius(radius) {} double getArea() override { return 3.14 * _radius * _radius; } private: double _radius; }; class Rectangle : public Shape { public: Rectangle(double width, double height) : _width(width), _height(height) {} double getArea() override { return _width * _height; } private: double _width; double _height; };
为了实现“套筒”形状,我们创建了一个派生类 Cylinder
,它从 Circle
和 Rectangle
继承。然而,由于 Circle
和 Rectangle
都有 getArea()
函数,因此 Cylinder
将面临钻石继承问题。
class Cylinder : public Circle, public Rectangle { public: Cylinder(double radius, double height) : Circle(radius), Rectangle(radius, height) {} };
为了避免钻石继承,我们使用虚继承:
class Cylinder : public virtual Circle, public virtual Rectangle { public: Cylinder(double radius, double height) : Circle(radius), Rectangle(radius, height) {} };
现在,Cylinder
类的 getArea()
函数总是调用它派生的最具体类(即 Cylinder
Base1
및 Base2
는 가상 상속을 사용합니다. 이렇게 하면 Derived::print()
가 항상 Derived
클래스의 구현을 호출하게 됩니다. 🎜🎜🎜실용 사례🎜🎜🎜그래프의 면적을 계산하는 예를 생각해 보세요. 면적 계산을 위한 getArea()
함수를 정의하는 기본 클래스 Shape
가 있습니다. 또한 모양별 면적 계산을 제공하는 두 개의 파생 클래스인 Circle
및 Rectangle
이 있습니다. 🎜rrreee🎜"슬리브" 모양을 구현하기 위해 Circle
및 Rectangle
에서 상속되는 파생 클래스 Cylinder
를 만들었습니다. 그러나 Circle
및 Rectangle
에는 모두 getArea()
함수가 있으므로 Cylinder
는 다이아몬드 상속 문제에 직면하게 됩니다. 🎜rrreee🎜다이아몬드 상속을 피하기 위해 가상 상속을 사용합니다. 🎜rrreee🎜이제 Cylinder
클래스의 getArea()
함수는 항상 자신이 파생된 가장 구체적인 클래스를 호출합니다. (예: 실린더
) 구현. 🎜위 내용은 C++ 함수 상속에 대한 자세한 설명: '다이아몬드 상속' 문제를 피하는 방법은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!