从零开始的C++(三)

1.引用与指针的相同与不同:

相同:底层逻辑相同,在汇编那层引用和指针是一致的,换句话说,引用就是被装饰后的指针,虽然外表有所差异,但内在是相同的。

不同:

1.定义的时候,引用必须要初始化,指针可以不初始化。

 2.引用在初始化时引用一个对象,此后不能修改,指针指向的对象可以修改。

3.引用的对象不能是NULL,指针可以指向NULL。

4.用sizeof的时候,引用是返回引用类型的大小,指针是返回指针的大小(32位下4个字节,64位下8个字节)。

5.访问实体的方式不同,指针需要解引用,引用是通过编译器自己处理。

6.没有多级引用,有多级指针。

7.引用自增是引用的对象的值自增,指针自增是指针所指的地址自增。

8.引用使用起来更加安全。

9.引用是对对象起一个别名,指针是指向的对象的地址。

2.内联函数(inline)

宏可以用于写一些简单的函数,比如交换两个数的值。但用宏写函数时,由于宏的特性,常会引起一些错误,比如漏加括号导致计算结果和预想的不同。内联函数就是为了解决宏的这些缺点而产生的。

内联函数的关键字是inline,放在函数返回类型的前面,如下所示,add函数是一个内联函数。

inline int add(int a, int b)
{
	return a + b;
}

内联函数和宏一样,在预编译阶段展开(即预编译阶段会把所有调用该函数的地方用函数的内容替换),因此说内联函数拥有宏的特点,但同时它的写法又酷似函数,因此也同样有函数的特点。

内联函数的特点:

1.和宏一样在预编译阶段展开,没有栈的开辟与销毁,是一种以空间换时间的做法。

2.内联函数是向编译器建议和宏一样展开,但如果内联函数内的代码很长,编译器仍会以函数的方式对待(即在运行阶段开辟、销毁函数栈帧)。

3.内联函数的定义和声明必须放在一块,不能出现声明放头文件,定义放.cpp的文件中,因为内联函数是像宏一样展开,而不是像函数一样跳转到函数所在的地址,所以头文件链接不到。

3.NULL的变化

在c语言中,NULL的类型是(void*)0,但在C++中NULL就是数字0,因此C++引用nullptr(全小写)来代替NULL给指针赋值。

4。初始类和对象

所谓类和对象,就是关注具体的事物,而不关心事物的特征和其动作。在C++中,像struct定义的结构体也成为了类的一种。但和c语言不同的一点是在C++中可以在struct中定义函数。

类的定义:

常用关键词class,也可以用struct,(两者的区别放在下面揭晓)如下图定义了一个名叫home的类,类中有成员变量child、child_num,有成员函数ge_cnum。

class home
{
   public:
   void get_cnum()
   {
     return child_num;  
   }

   private:
   char child[20];
   int  child_num;

};

常见的类的定义方式有两种,一种是类的成员函数和成员变量一块定义,一种是类的成员变量和成员函数的声明放在.h文件中,类的成员函数的定义放在.cpp文件中。需注意,若成员函数在类内定义,则编译器可能会认为其是内联函数。

当类的成员函数和成员变量分开定义的时候,成员函数的写法需要在返回类型和函数名之间加上

“类名::”,如下图所示:

从零开始的C++(三)_第1张图片从零开始的C++(三)_第2张图片

在用成员函数的时候,有时候可能会面临函数的形参名和类的成员变量名相同的情况,在这时函数内调用该名字是调用谁?

从零开始的C++(三)_第3张图片

答案是两个val都会代表形参名,因此设计类内函数的时候,请务必注意形参名和类的成员变量名是否相同,一般都会在成员变量名前或后加一个“_”来区分。但若真想把成员变量名和形参名设计的一样,又想要调用形参,该怎么办?

class node
{

	void get_val(int val)
	{

		this->val = val;

	 }

	int val;


};

答案是用this指针,此时this->val就是成员变量了,而没有this指针指向的val仍是形参。

类的访问权限:

类的访问权限有public、protected、private三种,此处先认为protected和private相同(因为两种的区别是在继承阶段,现在还没有写到继承),此处主要分析public和private的不同。

类的权限的管理范围是从该权限出现的那行开始,到下一个权限出现的地方或到类的结束。也就是说,在一个类中可能存在多个权限。

类的权限管理的是类内的一切,包括类内的成员函数和成员变量。

public的权限简单来说就是在类外也可以通过对象名.函数名的方式去使用,但是private下的在类外都不能使用。既然private下的无法在类外使用,那就只能在类内使用了,所谓在类内使用,就是用类内的成员函数来调用该成员变量。这样做的好处是无法随意修改类的成员变量和成员函数,更加的安全。

class和struct的区别便是不写权限时,class默认成员都是private,struct默认都是public,但只要写了权限两者就没有区别了。

类的作用域:

一个类就是一个新的作用域,类的所有成员都在此作用域中,这也说明了为什么在类外写函数定义需要加上作用域。(可以类比命名空间)

类的使用:和c语言的struct定义的结构体调用方式基本一致,但有时候可能会有所不同,不同之处下面再讲。

类的定义和声明:

声明只是说明类内有什么,但不会开辟实际的空间,只有类的定义才会开辟实际空间(就好比类的声明是一个计划书,类的定义是对计划的实施)。因此不能在声明了类以后就使用类.成员名去调用成员,而是创建实际的对象后用对象去调用成员。

类的大小:

类的大小和结构体的大小算法一致,也遵循字节对齐原则,同时,类的成员函数不算在类的大小中,因为类的成员函数实际是放在公共代码区而不是类内(这一点下面会考到!),和全局函数类似。然而,如果类中没有一个成员或者只有成员函数的时候,类的大小是多少?这取决于编译器,一般大小是1,但不管是什么编译器,类的大小都不会是0,因为至少需要有一个字节的大小去区分同一个类下的不同变量。类这种区分的方式叫占位,其作用是表示对象的区别。所开辟得到空间不是为了存储数据,而是为了说明有这个对象的存在。

this指针:

在C++中,this指针指向对象,用于存放对象的地址。this指针可以显示调用(即在成员函数中使用),但不能出现在形参中,因为编译器会默认调用this指针作为形参。也就是说,实际形参的个数比自己写的要多一个(this指针),在调用时实参的个数也比写的多一个(取对象的地址)。

5.C和C++的区别之一:

数据和方法是否分离(封装),在C中是分离的,C++中是封装在一起的,封装在一起可以杜绝随机访问,这也是C++的优势所在。

6.默认成员函数:

所谓默认成员函数,就是你不写编译器会自己写一个的函数,本篇中主要讲两个:默认构造函数和默认析构函数。

构造函数:

在对象创建的时候自动调用,用于对象的初始化。

特征:

1.构造函数名和类名必须一致。

2.构造函数无返回类型,即直接不写返回类型(这里要和void类型区分开)。

3.构造函数会在对象创建后自动调用。

4.构造函数可以有形参,因此可以构成函数重载。

5.当形参为空或全缺省时,对象的定义不能是 “类名 对象名()”,而应该是“类名 对象名”。因为前者编译器无法和函数声明进行区分。

默认构造函数:

默认构造函数有三种:无参构造函数、全缺省默认构造函数、不写构造函数时编译器自己写的构造函数。其特点是对象定义的时候不用加括号。

对于编译器自己写的构造函数,内置数据类型不会进行处理(如int、char、double、所以指针类型等),自定义类型会调用其默认构造函数。由于内置类型不会进行处理,所以允许在声明时给缺省值。如下图val在声明中赋值1,data在声明中被赋值2,data又在构造函数中被重新赋值,因此此时data=3,val=1.

从零开始的C++(三)_第4张图片

析构函数:

在对象销毁的时候调用,一般用于对成员的销毁。(如malloc、fopen等)。

析构函数的写法是~类名(),无返回类型,无形参。同时析构函数由于没有形参,因此没有函数重载。

析构函数和构造函数类似,不写的时候编译器会调用默认析构函数。(特点和默认构造函数类似)。

本篇讲了引用和指针的区别、内敛函数、NULL与nullptr、类和对象、构造函数、析构函数,粗略说明了c和C++的区别(封装)。

你可能感兴趣的:(c++,开发语言)