C++ 继承

“继承”允许一个类从另一个类中获得成员。在下面的例子中,“Square”继承自“Rectangle”。要指定继承的类,则需要在类定义后使用冒号并后跟public关键字和要继承的类名即可。“Rectangle”就会变为“Square”的基类,也即“Square”会按顺序变为“Rectangle”的导出类。除了它自身的成员外,“Square”也获得了所有“Rectangle”的可访问成员,不含基类的构造函数和析构函数。

class Rectangle
{
public:
  int x, y;
  int getArea() {return x * y;}
};
class Square : public Rectangle{};

向上转换(Upcasting)

一个对象可以根据其基类向上转换,因为该对象包含了它的基类所包含的一切。某个对象在以引用或指针指向其基类时执行“向上转换”。在下面的例子中,一个“Square”对象向上转换为“Rectangle”。当使用“Rectangle”的接口时,若只访问“Rectangle”的可访问成员,则“Square”对象将被视为“Rectangle”对象。

Square s;
Rectangle& r = s;  // reference upcast
Rectangle* p = &s; // pointer upcast

派生类可以在任何需要基类的地方使用。例如,可以将Square对象作为参数传递给需要Rectangle对象的函数。然后,派生对象将隐式升级为其基本类型。

void setXY(Rectangle& r)
{
  r.x = 2;
  r.y = 3;
}
int main()
{
  Square s;
  setXY(s);
}

向下转换

指向Square对象的Rectangle引用可以向下转换回Square对象。由于不允许将实际的矩形向下转换为Square,因此必须明确说明此向下转换。

Square& a = (Square&) r;  // reference downcast
Square& b = (Square&) *p; // pointer downcast

构造函数继承

为确保基类中的字段正确初始化,当创建派生类的对象时,将自动调用基类的无参数构造函数。

#include <iostream>
using namespace std;
class B1
{
 public:
  int x;
  B1() : x(5) {}
};
class D1 : public B1 {};
int main()
{
  D1 d; // calls parameterless constructors of D1 and B1
  cout << d.x; // "5"
}

可以通过将派生构造函数放在构造函数的初始化列表中来显式进行对基本构造函数的调用。这允许将参数传递给基本构造函数。

class B2
{
 public:
  int x;
  B2(int a) : x(a) {}
};
class D2 : public B2
{
 public:
  D2(int i) : B2(i) {} // call base constructor
};

这种情况下的替代解决方案是继承构造函数。从C++ 11开始,这可以通过using语句完成。

class D2 : public B2
{
 public:
  using B2::B2; // inherit all constructors
  int y {0};
};
int main()
{
  D2 d(3);
  cout << d.x; // "3"
}

请注意,基类构造函数无法初始化派生类中定义的字段。 因此,在派生类中声明的任何字段都应自行初始化。 这是使用统一符号完成的。

多重继承

C++ 允许派生类从多个基类继承。这称为多重继承。然后在逗号分隔的列表中指定基类。

class Person {}
class Employee {}
class Teacher: public Person, public Employee {}

多重继承并不常用,因为大多数现实世界的关系可以通过单一继承更好地描述。它还趋向于显着增加代码的复杂性。

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据