# C++面向对象

# 一、C++ 类构造函数 & 析构函数

构造函数在类中定义,在每次创建该类的变量时,构造函数都会执行一次。(可以用来给类传递参数)

#include <iostream>
 
using namespace std;
 
class Line
{
   public:
      void setLength( double len );
      double getLength( void );
      Line(double len);  // 这是构造函数
 
   private:
      double length;
};
 
// 构造函数定义
Line::Line( double len)
{
    cout << "Object is being created, length = " << len << endl;
    length = len;
}
 
void Line::setLength( double len )
{
    length = len;
}
 
double Line::getLength( void )
{
    return length;
}
// 程序的主函数
int main( )
{
   Line line(10.0);
 
   // 获取默认设置的长度
   cout << "Length of line : " << line.getLength() <<endl;
   // 再次设置长度
   line.setLength(6.0); 
   cout << "Length of line : " << line.getLength() <<endl;
 
   return 0;
}

在构造函数中赋值的时候,可以直接这样:

Line::Line( double len): length(len)
{
    cout << "Object is being created, length = " << len << endl;
}
//上下等价
Line::Line( double len)
{
    length = len;
    cout << "Object is being created, length = " << len << endl;
}

析构函数与构造函数相反,在类变量被删除时运行,定义如下,也是在类中定义:

~Line();  // 这是析构函数声明

# 二、基类与派生类

派生类继承基类中所有元素,一个派生类可以继承多个基类,如下:

class Shape
{
	public:
    	int func(int a)
        {
			a=1;
        }
    protected:
    	int b;
}
// 派生类
class Rectangle: public Shape//如此继承
{
   public:
      int getArea()
      { 
         return (width * height); 
      }
};

继承类型:public、protected、private。

  • public:继承基类的所有,原封不动(原来是public继承也是public,原来是protected,继承以后也是protected)
  • protected:继承基类的所有,并全部转化为protected型
  • private:继承基类的所有,并全部转化为protected型

# 三、函数重载与运算符重载

  • 函数重载:就是在类中可以定义相同函数名的函数,但是必须传入不同参数;

  • 运算符重载:通过关键字operator确定,如下:

    // 重载 + 运算符,用于把两个 Box 对象相加
          Box operator+(const Box& b)
          {
             Box box;
             box.length = this->length + b.length;
             box.breadth = this->breadth + b.breadth;
             box.height = this->height + b.height;
             return box;
          }
    

    在一个程序中,如果运算符被重载了,那原来的运算符就会被覆盖,无法使用。

# 四、cpp的多态

其实就是静态和动态。静态--无法改变;动态--可以动态改变。

一般体现在继承类与基类之间,即继承类重新定义了基态中已有的元素,此时编译器不知道访问哪个,因此报错。

解决方法,在基态该元素之前加上一个Vitual

  • 虚函数 是在基类中使用关键字 virtual 声明的函数。在派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数。

我们想要的是在程序中任意点可以根据所调用的对象类型来选择调用的函数,这种操作被称为动态链接,或后期绑定

# 五、数据抽象与封装

  • # 数据抽象

    cpp中,iostream也是一种类,该类中的cout就是一种抽象,即不需要理解内在实现过程,只需要调用这个对象即可。这是一种思路,主要用于用户不知道具体实现逻辑,只需要调用能调用的函数就能完成操作。

    这种思路在类的使用中很常见,譬如调用private中元素的值的时候,使用public的get()函数,而不是直接访问该值。

  • # 数据封装

    封装是面向对象编程中的把数据和操作数据的函数绑定在一起的一个概念,这样能避免受到外界的干扰和误用,从而确保了安全。数据封装引申出了另一个重要的 OOP 概念,即数据隐藏数据封装是一种把数据和操作数据的函数捆绑在一起的机制,数据抽象是一种仅向用户暴露接口而把具体的实现细节隐藏起来的机制。

# 六、抽象类(ABC)

抽象类其实就是带纯虚函数的类。

如果类中至少有一个函数被声明为纯虚函数,则这个类就是抽象类。纯虚函数是通过在声明中使用 "= 0" 来指定的,如下所示:

class Box
{
   public:
      // 纯虚函数
      virtual double getVolume() = 0;
   private:
      double length;      // 长度
      double breadth;     // 宽度
      double height;      // 高度
};
  • 设计抽象类(通常称为 ABC)的目的,是为了给其他类提供一个可以继承的适当的基类。抽象类不能被用于实例化对象,它只能作为接口使用。

  • 抽象类可以被称为接口,但不同于纯粹的接口,抽象类可以包含非纯虚函数和成员变量,而纯接口(或者称为接口类)通常只包含纯虚函数,没有成员变量和非纯虚函数。