day35-c++类继承

day35-c++类继承

一、c++继承概念

C++继承是面向对象程序设计中的一个重要概念,它允许我们根据一个已有的类来创建一个新的类,从而实现代码的重用和扩展。C++支持三种继承方式:公有继承、保护继承和私有继承,它们影响了基类和派生类之间成员的访问权限。C++还支持多继承,即一个派生类可以有多个基类,继承了它们的特性。在多继承中,有时会出现菱形继承的情况,即多个基类继承自同一个祖先类,导致派生类拥有重复的祖先类成员。为了解决这个问题,C++引入了虚继承和虚基类的概念,使得派生类只保留一份祖先类成员。

友员函数可以继承。




二、c++继承基础语法

C++继承语法的一般形式是:

class 派生类名 : 继承方式 基类名 {
  派生类的成员
}

  其中,继承方式可以是public(公有)、protected(保护)或private(私有)三种之一,用来指定基类的成员在派生类中的访问权限。
  如果不指定继承方式,默认为private。

  public是将基类的公有成员和保护成员继承给子类,且权限不变
  protected是将基类的公有成员和保护成员继承给子类,并且权限变为protected,不能在外部访问。Protected继承也保持了父类和子类之间的is-a(继承,子类是父类的一种特殊情况)关系,但是这种关系对外部不可见。
  private是将基类的共有成员和保护成员继承给子类,并且权限变为private。Private继承破坏了父类和子类之间的is-a关系,即子类不是一种特殊的父类。Private继承相当于把父类作为一个组件嵌入到子类中,实现了has-a(组合,一个类包含另一个类的对象)关系。

  例如,下面的代码定义了一个基类Animal和一个派生类Dog,Dog继承了Animal的所有成员,并增加了自己的成员函数bark()。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Animal {
public:
void eat() {
cout << "Animal is eating." << endl;
}
void sleep() {
cout << "Animal is sleeping." << endl;
}
};

class Dog : public Animal {
public:
void bark() {
cout << "Dog is barking." << endl;
}
};
// 这样,我们就可以通过Dog类的对象来调用Animal类的成员函数,以及Dog类自己的成员函数,如下:
Dog d;
d.eat(); // 调用基类的成员函数
d.sleep(); // 调用基类的成员函数
d.bark(); // 调用派生类的成员函数



三、c++继承的构造和析构顺序

当创建一个派生类的对象时,会先调用基类的构造函数,然后再调用派生类的构造函数。如果基类有多个,那么会按照声明的顺序从左到右依次调用基类的构造函数。如果基类或派生类有成员对象,那么会在调用自身的构造函数之前先调用成员对象的构造函数。如果基类的构造函数有参数,那么需要在派生类的初始化列表中显式地传递参数给基类的构造函数。

其次,我们来看看析构函数的调用顺序。当销毁一个派生类的对象时,会先调用派生类的析构函数,然后再调用基类的析构函数。如果基类有多个,那么会按照声明的顺序从右到左依次调用基类的析构函数。如果基类或派生类有成员对象,那么会在调用自身的析构函数之后再调用成员对象的析构函数。

gouzhao




四、c++继承的赋值

  • 派生类的对象可以赋值给基类的对象,但是会发生对象切割,即派生类特有的成员会被忽略。
  • 基类的对象不能赋值给派生类的对象,因为基类的对象可能缺少派生类需要的成员。
  • 派生类的指针或引用可以赋值给基类的指针或引用,这样可以实现多态,即通过基类的指针或引用调用派生类的虚函数。
  • 基类的指针或引用不能赋值给派生类的指针或引用,除非使用强制类型转换,但是这样做可能会导致运行时错误。



五、c++继承的重名问题

在c++中,继承是一种实现代码复用和多态的重要机制。继承允许一个类(子类)从另一个类(父类)继承成员变量和成员函数,从而实现对父类的扩展和修改。但是,如果子类和父类中有同名的成员,那么就会出现重名问题,也就是说,子类中的同名成员会隐藏父类中的同名成员,导致访问冲突和歧义。

为了解决这个问题,c++提供了以下几种方法:

  • 使用作用域限定符(::)来指定访问哪个类中的同名成员。例如,如果子类A继承了父类B,并且都有一个同名的函数f(),那么可以通过A::f()来调用子类中的f(),或者通过B::f()来调用父类中的f()。
  • 使用虚函数(virtual)来实现多态。虚函数是一种特殊的成员函数,它可以被子类重写(override),从而实现不同的行为。如果子类和父类中都有一个同名的虚函数f(),那么当通过父类指针或引用来调用f()时,会根据对象的实际类型来动态绑定(dynamic binding),调用相应的子类或父类中的f()。这样就可以避免歧义,并且提高了代码的灵活性和可维护性。
  • 使用using声明(using declaration)来引入父类中的同名成员到子类的作用域中。这样可以使得子类和父类中的同名成员都可以被访问,而不需要使用作用域限定符。例如,如果子类A继承了父类B,并且都有一个同名的变量x,那么可以在子类A中使用using B::x;来引入父类中的x到子类的作用域中。这样就可以通过x来访问子类或父类中的x。
Donate
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.
  • Copyrights © 2020-2024 nakano-mahiro
  • Visitors: | Views:

请我喝杯咖啡吧~

支付宝
微信