从零开始学c++——类与对象

Posted sjp11

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从零开始学c++——类与对象相关的知识,希望对你有一定的参考价值。

在这里插入图片描述

一.再谈构造函数

1.构造函数体的赋值

在构造函数体内进行赋值称为函数体内初始化。
在这里插入图片描述
然而上述构造函数调用之后,对象中已经有了一个初始值,但是不能将其称作为类对象成员的初始化,构造函数体中的语句只能将其称作为赋初值,而不能称作初始化。因为初始化只能初始化一次,而构造函数体内可以多次赋值。

2.初始化列表的定义

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

如下:
在这里插入图片描述

注意:
1.初始化列表只能初始化成员变量一次)
2

a.const 成员变量 b.引用成员变量c.自定义类型成员变量(该类没有默认的构造函数)都必须使用初始列表初始化

3.初始化列表可以跟函数体内初始化混着用

首先我们得知道, 类中的成员变量仅仅是声明的地方,当对象开始创建时,成员变量才会被定义出来 ,所以在引用成员变量是成立的,与引用定义时必须初始化是没有矛盾的。
在这里插入图片描述

错误例子:
在这里插入图片描述

初始化列表的意义:
一个对象的成员变量在初始化列表是它定义的阶段,有些成员变量在定义的阶段就必须要有初始化,比如const成员变量,引用成员变量,自定义成员变量,它们不能在函数体内初始化,只能在初始化列表的初始化

注意:
在c++中,成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关,如下这题:

在这里插入图片描述

A. 输出1 1
B. 程序崩溃
C.编译不通过
D.输出1 随机值

答案:D
因为成员变量在类中声明次序就是其在初始化列表中的初始化顺序,上述代码中,先声明_a2,所以先初始化_a2,由于_a1还未初始化,为随机值,所以_a2为随机值。

3.C++的成员初始化新玩法

C++11支持非静态成员变量在声明时进行初始化赋值,但是要注意这里不是初始化,这里是给声明的成员变量缺省值

在这里插入图片描述

二.explicit关键字详解

首先, C++中的explicit关键字只能用于修饰只有一个参数的类构造函数, 它的作用是表明该构造函数是显示的, 而非隐式的。

在这里插入图片描述

上面代码中的“ A a2=9 " 为什么可以呢?在c++中,在C++中, 如果的构造函数只有一个参数时, 那么在编译的时候就会有一个缺省的转换操作:将该构造函数对应数据类型的数据转换为该类对象,也就是说“ A a2=9 "这段代码在编译的时候同等于以下操作:

A a2(9)
或者
A tmp(9//先将int型转化为A型,发生了隐式类型转换
A a2=tmp;

但是, 上面的代码中的_size代表的是字符串内存分配的大小, 那么调用 " A a2= 9;" 和 " A a3 = ‘a’;" 就显得不伦不类, 而且容易让人疑惑. 有什么办法阻止这种用法呢? 答案就是使用explicit,如下

在这里插入图片描述

总结:
1.explicit关键字的作用是防止类构造函数的隐式类型自动转换

2.explicit关键字只对有一个参数的类构造函数有效, 如果类构造函数参数大于或等于两个时, 是不会产生隐式转换的, 所以explicit关键字也就无效了
3.但是, 也有一个例外, 就是当除了第一个参数以外的其他参数都有默认值的时候, explicit关键字依然有效, 此时, 当调用构造函数时只传入一个参数, 等效于只有一个参数的类构造函数, 例子如下:

在这里插入图片描述

三.static成员

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

在这里插入图片描述

在这里插入图片描述

获取静态成员变量;

在这里插入图片描述

题目:计算一个程序中定义出多少个对象出来?

思路:静态成员变量是存在静态区的,生命周期是全局的,还有每定义出一个对象都会调用一次构造函数,所以我们可以定义一个静态成员变量_n,然后在构造函数中++_n即可,代码如下:
在这里插入图片描述
`

总结:

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

问题:
1.静态成员函数可以调用非静态成员吗?

答案:不可以,因为访问非静态成员需要有this指针,而静态成员函数中没有this指针,所以访问不了。

  1. 非静态成员函数可以调用类的静态成员函数吗?

答案:可以,因为访问静态成员函数在类中不受访问限定符的限制

四.友元

友元分为:友元函数和友元类

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

1.友元函数

为了使其他类的成员函数直接访问该类的私有变量。即:允许外面的类或函数去访问类的私有变量和保护变量,从而使两个类共享同一函数。

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

如下:
在这里插入图片描述

实际上具体大概有下面两种情况需要使用友元函数:

(1)运算符重载的某些场合需要使用友元。

(2)两个类要共享数据的时候。

友元函数的参数:因为友元函数没有this指针
要访问非static成员时,需要对象做参数;
要访问static成员或全局变量时,则不需要对象做参数;

友元函数的位置: 因为友元函数是类外的函数,所以它的声明可以放在类的私有段或公有段且没有区别。

运算符重载<<的友元
在这里插入图片描述

所以想重载cout<<需要定义一个友元
在这里插入图片描述

总结:
1.友元函数可访问类的私有和保护成员,但不是类的成员函数
2.友元函数不能用const修饰
3.友元函数可以在类定义的任何地方声明,不受类访问限定符限制
4. 一个函数可以是多个类的友元函数

2.友元类

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

1.友元关系是单向的,不具有交换性。

若在A类中声明B类为其友元类,则B类可以直接访问A类中的私有成员,但A类中不能访问B类的私有成员。

2.友元关系是不能传递的

如果B是A的友元,C是B的友元,则不能说明C是A的友元。

在这里插入图片描述

5.内部类

概念:如果一个类A定义在另一个类B的内部,则A为B的内部类,B为A的外部类,A能够访问B中的所有成员,但B不能访问A的私有成员。
特性:
1.内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去调用内部类
2.内部类就是外部类的友元类。注意友元类的定义,内部类可以通过外部类的对象参数来访问外部类中的所有成员。但是外部类不是内部类的友元
3.注意内部类可以直接访问外部类中的static、枚举成员,不需要外部类的对象/类名
4. 内部类可以定义在外部类的public、protected、private都是可以的
5. sizeof(外部类)=外部类,和内部类没有任何关系。
在这里插入图片描述

点个赞呗~

以上是关于从零开始学c++——类与对象的主要内容,如果未能解决你的问题,请参考以下文章

从零开始学c++——string

C/C++编程笔记:C++单例模式详细解析!从零开始学懂单例

从零开始C++系列 c++ 入门

从零开始C++系列 c++ 入门

从零开始C++系列 c++ 入门

从零开始C++系列 c++ 入门