C++ Section2 面向对象(1)

面向对象的三大特性

三大特性:封装,继承,多态。

  1. 封装:封装是实现面向对象程序设计的第一步,封装就是将数据或函数等集合在一个个的单元中(我们称之为类)。封装的意义在于保护或者防止代码(数据)被我们无意中破坏。
  2. 继承:继承主要实现重用代码,节省开发时间。子类可以继承父类的一些东西。
  3. 多态:同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。分为编译时多态和运行时多态。

可被继承及不可被继承

无法被继承的有:

  • 构造函数
  • 析构函数
  • 赋值运算符
  • 友元函数

可被继承的有:

  • 静态成员
  • 静态方法
  • 非静态成员
  • 非静态方法
  • 虚表指针

定义默认构造函数的两种方法

  • 给已有的构造函数中的一个的所有参数加上默认值
  • 通过方法重载定义一个无参数构造函数

注意:隐式调用默认构造函数不要加括号(), 会被编译器解释为函数声明。

调用非默认构造函数的三种方法

  1. Foo f(…); // 隐式调用
  2. Foo f = Foo(…) ;// 显式调用
  3. Foo* f = new Foo(); // 显式调用

由编译器生成的六个成员函数

  1. 默认构造函数
  2. 析构函数
  3. 复制构造函数
  4. 赋值运算符
  5. 取地址运算符
  6. 取地址运算符 const版本
1
2
3
4
5
6
7
8
9
class Foo {
public:
Foo(); // 默认构造函数
~Foo(); // 析构函数
Foo(const Foo &); // 复制构造函数
const Foo& operator=(const Foo &); // 赋值构造函数
Foo* operator&(); // 取地址运算符
const Foo* operator&() const; // 取地址运算符const重载
};

必须在构造函数初始化式里进行初始化的数据成员

  1. 常量成员,因为常量只能初始化不能赋值,所以必须放在初始化列表里面
  2. 引用类型,引用必须在定义的时候初始化,并且不能重新赋值,所以也要写在初始化列表里面
  3. 没有默认构造函数的类类型,因为使用初始化列表可以不必调用默认构造函数来初始化,而是直接调用拷贝构造函数初始化

如果赋值构造函数参数不是传引用而是传值会有什么问题?

如果不是传引用,会造成栈溢出。因为如果是Foo(Foo f)的形式,实参初始化形参的时候也会调用复制构造函数,造成死循环。所以,复制构造函数一定要传引用:

Foo(Foo& f);

三种继承方式(public, private, protected)的区别

  1. 公有继承(public):

    • 基类成员对其对象的可见性: 与一般类及其对象的可见性相同,public成员可见,protectedprivate成员不可见。
    • 基类成员对派生类的可见性: 对派生类来说,基类的 publicprotected 成员可见的。
      • 基类的 public 成员和 protected 成员作为派生类的成员时,它们都保持原有状态;
      • 基类的 private 成员依旧是private,派生类不可访问基类中的private成员。
    • 基类成员对派生类对象的可见性: 对派生类对象来说,基类的public成员是可见的,其他成员是不可见的。所以,在公有继承时,派生类的对象可以访问基类中的public成员,派生类的成员方法可以访问基类中的public成员和protected成员。
  2. 私有继承(private):

    • 基类成员对其对象的可见性: 与一般类及其对象的可见性相同,public成员可见,其他成员不可见。
    • 基类成员对派生类的可见性: 对派生类来说,基类的public和protected成员可见:
      • 基类的 public 成员和 protected 成员都作为派生类的 private 成员,并且不能被这个派生类的子类所访问;
      • 基类的 private 成员依旧是private,派生类不可访问基类中的private成员。
    • 基类成员对派生类对象的可见性: 对派生类对象来说,基类的所有成员都是不可见的,所以在私有继承时,基类的成员只能由直接派生类访问,无法再往下继承
  3. 保护继承(protected):

    • 保护继承与私有继承相似,基类成员对其对象的可见性与一般类及其对象的可见性相同,public成员可见,其他成员不可见。
    • 基类成员对派生类的可见性: 对派生类来说,基类的public和protected成员是可见的:
      • 基类的 public 成员和 protected 成员都作为派生类的 protected 成员,并且不能被这个派生类的子类所访问;
      • 基类的 private 成员依旧是private,派生类不可访问基类中的private成员。
    • 基类成员对派生类对象的可见性: 对派生类对象来说,基类的所有成员都是不可见的。所以,在保护继承时,基类的成员也只能由直接派生类访问,而无法再向下继承

C++支持多重继承。多重继承是一个类从多个基类派生而来的能力。派生类实际上获取了所有基类的特性。当一个类 是两个或多个基类的派生类时,派生类的构造函数必须激活所有基类的构造函数,并把相应的参数传递给它们 。

class 与 struct的区别

  • class默认的继承方式为private, struct 默认继承方式为public
  • class的成员访问默认为private, struct默认为public