欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

c++类和对象详细总结

程序员文章站 2022-07-13 22:22:40
...

类和对象

空类

空类并不是什么都没有的,任何一个类在我们不写的情况下,都会自动生成六个默认成员函数:
c++类和对象详细总结

构造函数:主要内容不是开空间创建对象,而是初始化对象

构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用,保证每个数据成员 都有 一个合适的初始值,并且在对象的生命周期内只调用一次
特性:

(1):函数名与类名相同,无返回值,可以重载,对象实例化时编译器自动调用;
(2):有无参构造和带参构造;
(3):只有当类中没有任何构造函数时,编译器才会自动生成一个无参构造,如果类中已经定义了构造函数,那么编译器就不会再自动生成无参构造,即使类中没有显式定义无参构造;
(4):无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。注意:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为是默认成员函数。

初始化列表:以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括 号中的初始值或表达式。

注意:

  1. 每个成员变量在初始化列表中只能出现一次(初始化只能初始化一次),成员变量的定义是在初始化列表中的;
  2. 类中包含以下成员,必须放在初始化列表位置进行初始化:
  3. 引用成员变量(定义时必须初始化)
    a. const成员变量(定义时必须初始化)
    b.类类型成员(该类没有默认构造函数)

.成员变量在初始化列表中的初始化顺序,与声明顺序一致,与其在初始化列表中的顺序无关;最好初始化列表中的成员变量顺序与声明顺序一致;

explicit关键字:用explicit修饰构造函数,将会禁止单参构造函数的隐式转换

构造函数不仅可以构造与初始化对象,对于单个参数的构造函数,还有类型转换的作用(隐式类型转换)

class Date { 
public:
      Date(int year)
             :_year(year)
       {}
      explicit Date(int year)
             :_year(year)
      {}
 private:
       int _year;
       int _month:
       int _day; 
}void TestDate() {
    Date d1(2018);
// 用一个整形变量给日期类型对象赋值
// 实际编译器背后会用2019构造一个无名对象,最后用无名对象给d1对象进行赋值
    d1 = 2019;
 }

对于上面的代码,编译器先用2019构造一个匿名对象,再用匿名对象给d1赋值;这只针对单参构造函数;使用explicit关键字将会禁止这种隐式类型转换;

析构函数

与构造函数功能相反,析构函数不是完成对象的销毁,局部对象销毁工作是由编译器完成的。而 对象在销毁时会自动调用析构函数,完成类的一些资源清理工作
特性:

1:析构函数名是在类名前加上字符 ~。
2:无参数无返回值。
3: 一个类有且只有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。
4:对象生命周期结束时,C++编译系统系统自动调用析构函数。
5:如果有自定义对象,析构函数会自动调用自定义成员的析构函数,完成自定义成员的资源清理

拷贝构造:构造函数的重载形式,也是在创建对象是自动调用(传const & 不然会造成无穷递归)

**调用场景:**用已经存在的一个对象去创建一个新对象,创建的新对象和当前对象内容相同;

编译器默认生成的拷贝构造函数为字节拷贝,即浅拷贝(只拷贝对象模型中的内容,不拷贝资源)
如果有资源,必须显示定义拷贝构造,完成深拷贝;

赋值运算符重载函数:用一个对象修改已存在对象的值,让其内容改变

特性

1:如果没有定义,编译器自动生成;
2:如果需要连续赋值,函数返回值类型为当前类的引用;
3:可以通过 this != &(对象) 来判断是否是自己给自己赋值;
4:返回值一般为 *this;
5:编译器自动生成的赋值运算符重载函数完成字节拷贝,即浅拷贝,只拷贝对象模型中的成员变量,不拷贝资源;
6:如果类中有资源,则需要显示定义赋值运算符重载函数,完成深拷贝;

函数重载:

C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类 型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。
函数名字为:关键字operator后面接需要重载的运算符符号。
函数原型:返回值类型 operator操作符(参数列表)
注意

1:不能通过连接其他符号来创建新的操作符:比如aaa@qq.com;
2:重载操作符必须有一个类类型或者枚举类型的操作数 用于内置类型的操作符,其含义不能改变,例如:内置的整型+,不能改变其含义
3:作为类成员的重载函数时,其形参看起来比操作数数目少1成员函数的操作符有一个默认的形参this,限定为第一个形参
4:.* 、:: 、sizeof 、?: 、. 注意以上5个运算符不能重载。这个经常在笔试选择题中出现
5:如果是普通的函数,那么参数的个数与运算符需要的参数个数一致,如果是成员函数,那么显式定义的参数个数就少一个,因为编译器会传入this指针

取地址及const取地址操作符重载:获取对象的地址

这两个运算符一般不需要重载,使用编译器生成的默认取地址的重载即可,只有特殊情况,才需
要重载,比如让别人获取到指定的内容;

const成员

1:const修饰类的成员函数
将const修饰的类成员函数称为const成员函数,const修饰类成员函数,实际上是修饰该成员函数的this指针,表明在该成员函数中不能对类的任何成员变量进行修改

c++类和对象详细总结
2:思考下列问题

  1. const对象可以调用非const成员函数吗?
    不能;因为权限不能被放大
  2. 非const对象可以调用const成员函数吗?
    可以;因为权限并没有被放大;
  3. const成员函数内可以调用其它的非const成员函数吗?
    不可以;因为权限不能被放大;
  4. 非const成员函数内可以调用其它的const成员函数吗?
    可以;权限并没有被放大;

const对象的权限为只读
非const对象的权限为可读可写
原则:权限放大不被允许,权限缩小是被允许的;

注意:非成员函数不能用const修饰;因为非成员函数没有this指针;

static成员

概念:
声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用static修饰的 成员函数,称之为静态成员函数。静态的成员变量一定要在类外进行初始化

特性

1:静态成员为所有对象所共享,不属于具体某个实例;
2:静态成员变量必须在类外初始化,初始化时不添加static关键字,但要添加类作用域限定;
3:类静态成员即可用类名::静态成员或者对象.静态成员来访问
4:静态成员函数没有隐藏的this指针,不能访问任何非静态成员
5: 静态成员和类的普通成员一样,也有public、protected、private3种访问级别,也可以具有返回值
6:静态成员函数不能调用非静态成员函数/变量,非静态成员函数可以调用静态成员函数/变量;(原因为4)

友元

友元提供了一种突破封装的方式,有时提供了便利。但是友元会增加耦合度,破坏了封装,所以友元不宜多 用。

友元函数

友元函数可以直接访问类的私有成员,它是定义在类外部的普通函数,不属于任何类,但需要在类的内部声 明,声明时需要加friend关键字。

说明

1:友元函数可以访问类的私有成员,但它不是类的成员函数;
2:友元函数不能用const修饰,因为不是成员函数;
3:友元函数可以在类定义的任何地方声明,不受类访问限定符的限制;
4:一个函数可以是多个类的友元函数;
5:友元函数的调用与普通函数的调用和原理相同;

友元类

友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。

说明

1:友元关系是单向的,不具有交换性。
比如Time类和Date类,在Time类中声明Date类为其友元类,那么可以在Date类中直接访问Time 类的私有成员变量,但想在Time类中访问Date类中私有的成员变量则不行。
2:友元关系不能传递
如果B是A的友元,C是B的友元,则不能说明C时A的友元。

内部类

概念:如果一个类定义在另一个类的内部,这个类就叫做内部类;

注意:
1:内部类是一个独立的类,它不属于外部类,更不能外部类对象去调用内部类,外部类对内部类没有任何优越的访问权限;
2:内部类时外部类的友元类,可以通过外部类的对象参数来访问外部类中的所有成员。但外部类不是内部类的友元类;

特性

1:内部类可以定义在外部类的public,protected,private都是可以的;
2:内部类可以直接访问外部类中的static,枚举成员,不需要外部类的对象/类名;
3:sizeof(外部类) = 外部类,和内部类没有关系;

相关标签: c++基础 c++