跳转至

面向对象(一)

简述面向对象

  • 概念:面向对象是一种编程思想,把一切东西看成一个个对象,将对象的属性行为等打包成一个类来表示
  • 面向对象和面向过程区别
    • 面向过程:根据业务逻辑从上往下写代码
    • 面向对象:把整个需求按照特点,功能进行划分,将存在共性的部分封装成类,减少了重复代码的重写过程

面向对象三特征

  • 封装

    • 概念:将数据和方法进行有机结合,隐藏对象的属性以及实现细节,仅对外提供公开接口和对象进行交互
  • 继承

    • 概念:可以使用现有类的所有功能,无需重写原来的类就能对这些功能进行扩展
    • 写法实例
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Shape 
{
   public:
      void setWidth(int w)
      {
         width = w;
      }
      void setHeight(int h)
      {
         height = h;
      }
   protected:
      int width;
      int height;
};

// 派生类
class Rectangle: public Shape
{
   public:
      int getArea()
      { 
         return (width * height); 
      }
};
1
+ 三种继承方式:
继承方式 private继承 protected继承 public继承
基类的private成员 不可见 不可见 不可见
基类的protected成员 变为private成员 仍为protected成员 仍为protected成员
基类的public成员 变为private成员 变为protected成员 仍未public成员
  • 多态

    • 概念:用父类型的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数,调用成员函数时,会根据函数的对象类型来执行不同的函数,
    • 实现方式:重写,重载
    • 举例
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
Rectangle rec(10,7); 
Triangle  tri(10,5);

// 存储矩形的地址
shape = &rec; // 父类型指针指向子类实例
// 调用矩形的求面积函数 area
shape->area();

// 存储三角形的地址
shape = &tri;
// 调用三角形的求面积函数 area
shape->area();

C++重写与重载

  • 重写

    • 派生类中重写定义的函数,其参数列表,函数名,返回参数类型都与基类被重写函数相同,只有函数体不同,派生类调用函数时会调用派生类的重写函数,而不会调用被重写函数,重写和被重写函数前需要有virtual修饰
    • 举例
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#include<bits/stdc++.h>  
using namespace std;  

class A { 
    public:  
      virtual void fun()  {   cout << "A";  } 
}; 

class B :public A { //继承
    public:  
      virtual void fun()  {   cout << "B";  } //函数重写
}; 

int main(void) {  
      A* a = new B();  a->fun();//输出B,A类中的fun在B类中重写 
}
  • 重载

    • 在同一个作用域,声明几个功能类似的同名函数,但是这些函数的形参需不同,更具参数列表可确定调用那个函数
    • 举例
1
2
3
4
5
6
7
8
#include<bits/stdc++.h>  
using namespace std;  
class A {  
    void fun() {};  
    void fun(int i) {};  
    void fun(int i, int j) {};     
    void fun1(int i,int j){}; 
};

C++构造函数

默认构造函数,初始化构造函数,拷贝构造函数,移动构造函数

  • 默认构造函数
1
2
3
class Student { 
    public:  //默认构造函数  Student()  {     num=1001;        age=18;      }
}
  • 初始化构造函数
1
2
3
class Student {
    Student(int n,int a):num(n),age(a){}
}
  • 拷贝构造函数
    • 它只有一个参数,参数类型是本类的引用。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#include<iostream >
using namespace std;
class Complex
{
public:
    double real, imag;
    Complex(double r, double i) {
        real= r; imag = i;
    }
};
int main(){
    Complex cl(1, 2);
    Complex c2 (cl);  //用拷贝构造函数初始化c2
    cout<<c2.real<<","<<c2.imag;  //输出 1,2
    return 0;
}
  • 移动构造函数

只定义析构函数,会自动生成哪些构造函数

默认构造函数和拷贝构造函数


一个类默认生成哪些函数

  • 默认构造函数
1
run (){}
  • 拷贝构造函数
1
run (const run& copy) {}
  • 析构函数
1
~run(){}
  • 赋值运算符
1
run& operator = (const run& copy) {}

C++类对象的初始化顺序以及多重继承下的顺序

  • 父类构造函数>成员类构造函数>自身构造函数
  • 析构函数相反
  • 成员变量的初始化顺序与变量在类中声明顺序有关
  • 构造函数的调用顺序是类派生表中的顺序

向上转型和向下转型

  • 向上转型:子类转换为父类,相对安全
  • 向下转型:父类转换为子类,不安全
    • 原因:父类的指针或引用的内存中不一定包含子类成员的内存