C++升级篇

C++升级篇


C++类&对象

  • C++ 在 C 语言的基础上增加了面向对象编程,C++ 支持面向对象程序设计。类是 C++ 的核心特性,通常被称为用户定义的类型
  • 类用于指定对象的形式,它包含了数据表示法和用于处理数据的方法。类中的数据和方法称为类的成员。函数在一个类中被称为类的成员。

C++定义

class Box
{
   public:
      double length;   // 盒子的长度
      double breadth;  // 盒子的宽度
      double height;   // 盒子的高度
};

定义C++对象

Box Box1;          // 声明 Box1,类型为 Box
Box Box2;          // 声明 Box2,类型为 Box

访问数据成员

  • 类的对象的公共数据成员可以使用直接成员访问运算符**(.)** 来访问
#include <iostream>
 
using namespace std;
 
class Box
{
   public:
      double length;   // 长度
      double breadth;  // 宽度
      double height;   // 高度
};
 
int main( )
{
   Box Box1;        // 声明 Box1,类型为 Box
   Box Box2;        // 声明 Box2,类型为 Box
   double volume = 0.0;     // 用于存储体积
 
   // box 1 详述
   Box1.height = 5.0; 
   Box1.length = 6.0; 
   Box1.breadth = 7.0;
 
   // box 2 详述
   Box2.height = 10.0;
   Box2.length = 12.0;
   Box2.breadth = 13.0;
 
   // box 1 的体积
   volume = Box1.height * Box1.length * Box1.breadth;
   cout << "Box1 的体积:" << volume <<endl;
 
   // box 2 的体积
   volume = Box2.height * Box2.length * Box2.breadth;
   cout << "Box2 的体积:" << volume <<endl;
   return 0;
}

类&对象详解


概念描述
类成员函数类的成员函数是指那些把定义和原型写在类定义内部的函数,就像类定义中的其他变量一样
类访问修饰符类成员可以被定义为 public、private 或 protected。默认情况下是定义为 private
构造函数 & 析构函数类的构造函数是一种特殊的函数,在创建一个新的对象时调用。类的析构函数也是一种特殊的函数,在删除所创建的对象时调用
C++ 拷贝构造函数拷贝构造函数,是一种特殊的构造函数,它在创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象
C++ 友元函数友元函数可以访问类的 private 和 protected 成员
C++ 内联函数
C++ 中的 this 指针每个对象都有一个特殊的指针 this,它指向对象本身
C++ 中指向类的指针指向类的指针方式如同指向结构的指针。实际上,类可以看成是一个带有函数的结构。
C++ 类的静态成员类的数据成员和函数成员都可以被声明为静态的

类访问修饰符

  • 数据封装是面向对象编程的一个重要特点,它防止函数直接访问类类型的内部成员。类成员的访问限制是通过在类主体内部对各个区域标记public、private、protected来指定的。关键字public、private、protected称为访问修饰符
class Base {
 
   public:
 
  // 公有成员
 
   protected:
 
  // 受保护成员
 
   private:
 
  // 私有成员
 
};

成员
  • **公有成员(public)**在程序中类的外部是访问的
  • **私有成员(private)**变量或函数在类的外部是不可访问的,甚至是不可查看的。只有类和友元函数可以访问私有成员
  • **保护成员(protected)**保护成员变量或函数与私有成员十分相似,但有一点不同,保护成员在派生类(即子类)中是可访问的
#include <iostream>
using namespace std;
 
class Box
{
   protected:
      double width;
};
 
class SmallBox:Box // SmallBox 是派生类
{
   public:
      void setSmallWidth( double wid );
      double getSmallWidth( void );
};
 
// 子类的成员函数
double SmallBox::getSmallWidth(void)
{
    return width ;
}
 
void SmallBox::setSmallWidth( double wid )
{
    width = wid;
}
 
// 程序的主函数
int main( )
{
   SmallBox box;
 
   // 使用成员函数设置宽度
   box.setSmallWidth(5.0);
   cout << "Width of box : "<< box.getSmallWidth() << endl;
 
   return 0;
}

C++继承

  • 面向对象程序设计中最重要的一个概念是继承
  • 继承允许我们依据另一个类来定义一个类,这使得创建和维护一个应用程序变得更容易。这样做,也达到了重用代码功能和提高执行时间的效果
  • 当创建一个类时,您不需要重新编写新的数据成员和成员函数,只需指定新建的类继承了一个已有的类的成员即可。这个已有的类称为基类,新建的类称为派生类
基类 & 派生类
  • 一个类可以派生自多个类,它可以从多个基类继承数据和函数
  • 定义一个派生类,我们使用一个类派生列表来指定基类。类派生列表以一个或多个基类命名,形式如下:
class derived-class: access-specifier base-class
//access-specifier 是访问修饰符
继承类型
  • 当一个类派生自基类,该基类可以被继承为 public、protected 或 private 几种类型
  • 几乎不使用 protected 或 private 继承,通常使用 public 继承
    • 公有继承(public):当一个类派生自公有基类时,基类的公有成员也是派生类的公有成员,基类的保护成员也是派生类的保护成员,基类的私有成员不能直接被派生类访问,但是可以通过调用基类的公有和保护成员来访问。
    • 保护继承(protected): 当一个类派生自保护基类时,基类的公有和保护成员将成为派生类的保护成员。
    • 私有继承(private):当一个类派生自私有基类时,基类的公有和保护成员将成为派生类的私有成员。

访问控制和继承
  • 派生类可以访问基类中所有的非私有成员
  • 根据访问权限总结出不同的访问类型
    |访问|public|protected|private|
    |-|-|-|-|
    |同一个类|yes|yes|yes|
    |派生类|yes|yes|no|
    |外部的类|yes|no|no|

一个派生类继承了所有的基类方法,但下列情况除外:

  • 基类的构造函数、析构函数和拷贝构造函数。
  • 基类的重载运算符。
  • 基类的友元函数
多继承
  • 多继承即一个子类可以有多个父类,它继承了多个父类的特性
class <派生类名>:<继承方式1><基类名1>,<继承方式2><基类名2>,…
{
<派生类类体>
};

C++重载运算符合重载函数

  • C++ 允许在同一作用域中的某个函数和运算符指定多个定义,分别称为函数重载和运算符重载
  • 重载声明是指一个与之前已经在该作用域内声明过的函数或方法具有相同名称的声明,但是它们的参数列表和定义(实现)不相同
  • 当您调用一个重载函数或重载运算符时,编译器通过把您所使用的参数类型与定义中的参数类型进行比较,决定选用最合适的定义。选择最合适的重载函数或重载运算符的过程,称为重载决策

C++中函数重载

  • 在同一个作用域内,可以声明几个功能类似的同名函数,但是这些同名函数的形式参数(指参数的个数、类型或者顺序)必须不同。您不能仅通过返回类型的不同来重载函数。
#include <iostream>
using namespace std;
 
class printData
{
   public:
      void print(int i) {
        cout << "整数为: " << i << endl;
      }
 
      void print(double  f) {
        cout << "浮点数为: " << f << endl;
      }
 
      void print(char c[]) {
        cout << "字符串为: " << c << endl;
      }
};
 
int main(void)
{
   printData pd;
 
   // 输出整数
   pd.print(5);
   // 输出浮点数
   pd.print(500.263);
   // 输出字符串
   char c[] = "Hello C++";
   pd.print(c);
 
   return 0;
}
  • 整数为: 5
  • 浮点数为: 500.263
  • 字符串为: Hello C++

C++中的运算符重载

  • 重载,就是赋予新的含义,运算符重载和函数重载类似,同一个运算符可以有不同的功能
  • 运算符重载的方式就是定义一个函数,在函数体内实现想要的功能,当用到该运算符时,编译器就会自动调用这个函数。也就是说,运算符重载就是通过函数定义实现的,它本质上是函数重载
  • 重载运算符的规则:
  1. 并不是所有运算符都可以重载。例如长度运算符(sizeof)、条件运算符(: ?)、成员选择符(.)、对象选择符(.*)、域解析符(::)不能被重载
  2. 重载不能改变运算符的优先级和结合性
  3. 重载不会改变运算符的用法。例如"+"号总是出现在两个操作数之间
  4. 重载运算符的函数不能有默认的参数,否则就改变了运算符操作数的个数,显然是错误的
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <set>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <stack>
#include <queue>
using namespace std;

class Complex
{
private:
    double real;    //实部
    double imag;    //虚部
public:
    Complex(): real(0.0),imag(0.0) {}
    Complex(double a,double b):real(a),imag(b) {}


    friend Complex operator*(const Complex & A,const Complex & B);
    friend Complex operator/(const Complex & A,const Complex & B);
    friend Complex operator+(const Complex & A,const Complex & B);
    friend Complex operator-(const Complex & A,const Complex & B);

    void display() const;
};

/* + 运算符重载*/
Complex operator+(const Complex & A,const Complex & B) 
{
    Complex C;
    C.real = A.real + B.real;
    C.imag = A.imag + B.imag;
    return C;
};

/* - 运算符重载*/
Complex operator-(const Complex & A,const Complex & B)
{
    Complex C;
    C.real = A.real - B.real;
    C.imag = A.imag - B.imag;
    return C;
};

/* * 运算符重载*/
Complex operator*(const Complex & A,const Complex & B)
{
    Complex C;
    C.real = A.real * B.real - A.imag * B.imag;
    C.imag = A.imag * B.real + A.real * B.imag;
    return C;
};

/* / 运算符重载*/
Complex operator/(const Complex & A,const Complex & B)
{
    Complex C;
    double square = A.real*A.real + A.imag*A.imag;
    C.real = (A.real * B.real + A.imag * B.imag)/square;
    C.imag = (A.imag * B.real - A.real * B.imag)/square;
    return C;
};

void Complex::display() const 
{
    cout << real << "+" << imag << "i" << endl;
};

int main()
{
    Complex a(1.1,2.2);
    Complex b(3.3,4.4);

    Complex c;

    c = a + b; 
    cout << "a+b= ";
    c.display();


    c = a - b;
    cout << "a-b= ";
    c.display();

    c = a*b;
    cout << "a*b= ";
    c.display();

    c = a/b;
    cout << "a/b= ";
    c.display();

    return 0;
}
/*输出结果:
a+b= 4.4 + 6.6i
a-b= -2.2 + -2.2i
a*b= -6.05 + 12.1i
a/b= 2.2 + 0.4i
*/
  • 例2
#include <iostream>
using namespace std;
 
class Box
{
   public:
 
      double getVolume(void)
      {
         return length * breadth * height;
      }
      void setLength( double len )
      {
          length = len;
      }
 
      void setBreadth( double bre )
      {
          breadth = bre;
      }
 
      void setHeight( double hei )
      {
          height = hei;
      }
      // 重载 + 运算符,用于把两个 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;
      }
   private:
      double length;      // 长度
      double breadth;     // 宽度
      double height;      // 高度
};
// 程序的主函数
int main( )
{
   Box Box1;                // 声明 Box1,类型为 Box
   Box Box2;                // 声明 Box2,类型为 Box
   Box Box3;                // 声明 Box3,类型为 Box
   double volume = 0.0;     // 把体积存储在该变量中
 
   // Box1 详述
   Box1.setLength(6.0); 
   Box1.setBreadth(7.0); 
   Box1.setHeight(5.0);
 
   // Box2 详述
   Box2.setLength(12.0); 
   Box2.setBreadth(13.0); 
   Box2.setHeight(10.0);
 
   // Box1 的体积
   volume = Box1.getVolume();
   cout << "Volume of Box1 : " << volume <<endl;
 
   // Box2 的体积
   volume = Box2.getVolume();
   cout << "Volume of Box2 : " << volume <<endl;
 
   // 把两个对象相加,得到 Box3
   Box3 = Box1 + Box2;
 
   // Box3 的体积
   volume = Box3.getVolume();
   cout << "Volume of Box3 : " << volume <<endl;
 
   return 0;
}
/*
Volume of Box1 : 210
Volume of Box2 : 1560
Volume of Box3 : 5400
*/

C++多态

  • 多态按字面的意思就是多种形态。当类之间存在层次结构,并且类之间是通过继承关联时,就会用到多态
  • C++的多态性用一句话概括就是:在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会根据对象的实际类型来调用相应的函数。如果对象类型是派生类,就调用派生类的函数;如果对象类型是基类,就调用基类的函数
  • 多态性可以简单地概括为“一个接口,多种方法”,程序在运行时才决定调用的函数,它是面向对象编程领域的核心概念。
  • C++多态性是通过虚函数来实现的,虚函数允许子类重新定义成员函数,而子类重新定义父类的做法称为覆盖(override),或者称为重写。(这里我觉得要补充,重写的话可以有两种,直接重写成员函数和重写虚函数,只有重写了虚函数的才能算作是体现了C++多态性
  • 多态与非多态的实质区别就是函数地址是早绑定还是晚绑定。如果函数的调用,在编译器编译期间就可以确定函数的调用地址,并生产代码,是静态的,就是说地址是早绑定的。而如果函数调用的地址不能在编译器期间确定,需要在运行时才确定,这就属于晚绑定
  • 那么多态的作用是什么呢,封装可以使得代码模块化,继承可以扩展已存在的代码,他们的目的都是为了代码重用。而多态的目的则是为了接口重用。也就是说,不论传递过来的究竟是那个类的对象,函数都能够通过同一个接口调用到适应各自对象的实现方法
  • 最常见的用法就是声明基类的指针,利用该指针指向任意一个子类对象,调用相应的虚函数,可以根据指向的子类的不同而实现不同的方法。如果没有使用虚函数的话,即没有利用C++多态性,则利用基类指针调用相应的函数的时候,将总被限制在基类函数本身,而无法调用到子类中被重写过的函数。因为没有多态性,函数调用的地址将是一定的,而固定的地址将始终调用到同一个函数,这就无法实现一个接口,多种方法的目的了。
#include <iostream> 
using namespace std;

class Shape {
protected:
	int width, height;
public:
	Shape(int a = 0, int b = 0)//构造函数
	{
		width = a;
		height = b;
	}
	virtual int area()
	{
		cout << "Parent class area :" << endl;
		return 0;
	}
};
class Rectangle : public Shape {
public:
	Rectangle(int a = 0, int b = 0) :Shape(a, b) { }
	int area()
	{
		cout << "Rectangle class area :" << endl;
		return (width * height);
	}
};
class Triangle : public Shape {
public:
	Triangle(int a = 0, int b = 0) :Shape(a, b) { }
	int area()
	{
		cout << "Triangle class area :" << endl;
		return (width * height / 2);
	}
};
// 程序的主函数
int main()
{
	Shape *shape;
	Rectangle rec(10, 7);
	Triangle  tri(10, 5);

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

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

	return 0;
}
  • 多态
    • 静态多态
      • 函数重载
      • 泛型编程
    • 动态多态
      • 虚函数

c++纯虚数


  • 纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。在基类中实现纯虚函数的方法是在函数原型后加“=0”
  • virtual void funtion()=0
  • 引入原因
  1. 为了方便使用多态特性,我们常常需要在基类中定义虚拟函数。
  2. 在很多情况下,基类本身生成对象是不合情理的。例如,动物作为一个基类可以派生出老虎、孔雀等子类,但动物本身生成对象明显不合常理。
  • 为了解决上述问题,引入了纯虚函数的概念,将函数定义为纯虚函数(方法:virtual ReturnType Function()= 0;),则编译器要求在派生类中必须予以重写以实现多态性。同时含有纯虚拟函数的类称为抽象类,它不能生成对象。这样就很好地解决了上述两个问题
  • 多态性
    • 指相同对象收到不同消息或不同对象收到相同消息时产生不同的实现动作。C++支持两种多态性:编译时多态性,运行时多态性。
      • 编译时多态性:通过重载函数实现
      • 运行时多态性:通过虚函数实现
  • 虚函数
    • 虚函数是在基类中被声明为virtual,并在派生类中重新定义的成员函数,可实现成员函数的动态覆盖(Override)
  • 抽象类
    • 包含纯虚函数的类称为抽象类。由于抽象类包含了没有定义的纯虚函数,所以不能定义抽象类的对象。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值