C++类和对象的基础知识详解

C++类和对象

类构成了实现C++面向对象程序设计的基础。
类是C++封装的基本单元,它把数据和函数封装在一起。

一个类描述一类事物,描述这些事物所应具有的属性。

  • 定义成员函数

    • 类定义是提供给更多不同用途的程序共享的,并不受单个程序应用的影响而“优化”。
    • 在类中定义的成员函数一般规模都比较小,且特别的switch语句不允许使用。
    • 类中的函数一般为内联函数,即使没有明确用inline标明。
    • 在类中定义的成员被默认为内联函数。
  • 在类之后定义成员函数

    • 将类定义和其成员函数定义分开来,是目前开发程序的通常做法。
    • 我们把类定义(头文件)看成是类的外部接口,类的成员函数定义看成是类的内部实现。
    • 在类定义的外部定义成员函数,需要在成员函数名前多加上一个“类名: :”
    • 因为成员函数是所有对象共享的代码,不是某一个对象所独占的,所以不能在成员函数内使用某个特定的对象。
  • 隐含的this指针

    • 一般情况下,成员函数除了接受实参之外,还会接受到对象的地址。
    • 这个地址被一个隐含的形参this指针所获取,等同于执行this = &x;
    • 所有对数据成员的访问都隐含地被加上前缀this->。
    • 所有的成员函数都会默认有this指针,static类型的函数除外。
    • this指针是成员函数隐含指针形参,是编译器自己处理的,我们不能在成员函数的形参中添加this指针的参数定义,也不能在调用时
      显示传递对象的地址给this指针。
  • 类的访问限定符

    • public(公有)
      • 编制应用程序,想要使用某个类,所要了解的全部内容就是它的公共成员。
      • 公共成员在任何地方都可以被访问。
    • private(私有)
      • 一个类定义,如果不写访问控制说明符,那么它就默认为private。
      • 外部无法访问私有成员,而起到保护作用。
    • protected(保护)
      • 保护类的内部数据
      • 保护成员对使用者来说是不可见的
      • 对内部可见
      • 常用于继承
    • 类的访问限定符体现了面向对象的封装性。
  • 作用域

    • 局部域
    • 全局域
    • 类域
    • 名字空间域
  • 类的作用域

    类的作用域是指类定义和相应的成员函数定义范围

    • 每个类都定义了自己的作用域,类的成员(成员函数/成员变量)都在类的这个作用域内,成员函数内可任意访问成员变量和其它成员函数。
    • 对象可以通过 . 直接访问公有成员,指向对象的指针通过 -> 也可以直接访问对象的公有成员。
    • 在类体外定义成员,需要使用 :: 作用域解析符指明成员属于哪个类域。

对象

算法总是离不开数据结构,算法也只能适用于特定的数据结构。
在面向对象中,算法与数据结构被捆绑成一个类。
也就是说,程序就是许多对象在计算机中相继表现自己,而对象又是一个个程序实体。

一个对象是类的一个实例,它具有确定的属性。

  • 面向对象的三大特性

    • 封装
    • 继承
    • 多态
  • 类和对象的区别

    • 对象可以被创建和销毁,但类是无所不在的。
  • 定义对象

    • 属于不同类的对象在不同的时刻、不同的地方分别被建立。
    • 全局对象在主函数开始执行前首先被建立。
    • 局部对象在程序执行遇到它们的对象定义时才被建立。
    • 在定义对象时,C++会为其分配空间。
  • 对象的初始化

    • C++建立和初始化对象的过程专门由该类的构造函数来完成。
    • 只要对象建立,则马上会调用构造函数,给对象分配空间和初始化。
  • 对象的内存储存模型

    • 所有对象的大小为类中所有成员变量的大小之和。
    • 遵循内存对齐原则——以空间换时间。
    • 空类域占一个字节。

这里写图片描述

类的默认成员函数

构造函数

类的封装性,体现在一部分数据是不能让外界访问的。
所以直接在非成员函数中访问类对象的保护或私有数据是不允许的。

C++规定与类同名的成员函数是构造函数,在该类的对象创建时,自动被调用

  • 构造函数没有返回类型,函数体中也不允许返回值,但可以有无值返回语句“return”。
  • 构造函数不能被随意调用。
  • 放在外部定义的构造函数,其函数名前需要加上“类名: :”,以区分此类成员函数和彼类成员函数。

IMPORTANT
* C++规定,每个类必须有一个构造函数,没有构造函数,就不能创建任何对象。
* 若未提供一个类的构造函数,则C++提供一个默认的构造函数,该默认构造函数是个无参构造函数,它仅负责创建对象,而不做任何初始化工作。
* 只要一个类定义了一个构造函数(不一定是无参构造函数),C++就不再提供默认的构造函数。也就是说,如果为类定义了一个带参数的构造函数,还想要无参构造函数,则必须自己定义。
* 与变量定义类似,在用默认构造函数创建对象时,如果创建的是全局对象或静态对象,则对象的位模式全为0,否则,对象值是随机的。

构造函数成员的初始化
* 方法一

  d = 10;
  • 方法二
SillyClass2()
    :d(10)
    {}
  • 哪些成员变量必须放在初始化列表里面?
    1. 常量成员变量。(常量创建时必须初始化)
    2. 引用类型成员变量。(引用创建时必须初始化)
    3. 没有缺省构造函数的类成员变量。

拷贝构造函数

  • 用一个对象去构造另一个对象,或者说,用另一个对象值初始化一个新构造的对象
  • 拷贝构造函数的参数必须使用引用传参,使用传值方式会引发无穷递归调用。

析构函数

析构函数是特殊的类成员函数,它没有返回类型,没有参数,不能随意调用,也没有重载。只是在类对象生命期结束的时候,由系统自动调用。

  • 作为一个类,可能有许多对象,每当对象生命期结束时,都要调用析构函数。
  • 析构函数名,就是在构造函数名前加一个逻辑非运算符“~”,表示“逆构造函数”。
  • 如果动态开辟了空间,需要自己重新定义一个析构函数。

赋值运算符的重载

  • 为什么要有运算符的重载?

    • 可以把C++运算符的定义扩展到运算分量是对象的情况。
    • 使C++代码更直观,更易读。
  • 5个C++不能重载的运算符:

    • .*
    • ::
    • sizeof
    • ?:
    • .
  • operator + 合法的运算符 构成函数名(重载<运算符的函数名:operator< )。
  • 重载运算符以后,不能改变运算符的优先级/结合性/操作数个数。
  • 赋值运算符的重载是对一个已存在的对象进行拷贝赋值。
  • 增量运算符
    • 前增量

      &operator++();
    • 后增量

      opertor++(int);
阅读更多
换一批

没有更多推荐了,返回首页