C++的入门基础知识

const修饰符

1.为何在C++中const要比#define更加常用? 

在C语言中,习惯使用#define来定义常量,如:#define MAX 10000,实际上这种方法只是在预编译时进行字符置换,把程序中出现的标识符MAX全部置换为10000。在预编译后,程序中不再有MAX这个标识符。MAX不是变量,没有类型,不占用存储单元,而且容易出错。与#define定义的常量有所不同的是const定义的常量可以有自己的数据类型,这样C++的编译程序可以进行更加严格的类型检查,使编译时具有良好的检测性。除此之外,#define 只能用于程序的开头位置定义全局的常量,而const可以在程序中的任意位置定义常量(常量的作用域亦随定义位置的变化而变化)。因此C++建议用const取代#define定义常量。

2.使用const定义常量时时有什么需要注意的?

(1)如果用const定义的是一个整型常量,则关键字 “ int ” 可以省略。

(2)const与一般类型常量结合使用时,const既可以放在长了的类型修饰符前,又可以放在类型修饰符后,前者和后者是等价的。

如:const int MAX = 10000 和 int const MAX = 10000

(3)const与指针结合使用时,const摆放的位置不是随意的,放在类型指针修饰符前和后的效果是截然不同的。

当const放在类型指针修饰符前,如:const char* p,  此时字符型指针所指的常量的值不允许被改变。

当const放在类型指针修饰符后,如:char* const p,此时字符型指针所指的地址不允许被改变。

 

内联函数

1.为何C++中有函数的引入后,还要引入内联函数?

这主要是为了消除函数调用时的系统开销,以提高运行速度。一般在程序执行过程中调用函数时,系统要将程序当前的一些状态信息存到栈中,同时转到函数的代码处去执行函数体的语句,这些参数的保存于传递的过程中需要时间和空间的开销,使得程序执行效率降低,特别是在程序频繁调用函数时,这个问题会变得非常严重,为此,C++引入了内联函数。每当程序中出现对内联函数的调用时,C++编译器使用函数体中的代码插入到调用该函数的语句之处,同时用实参取代形参,以便在程序运行时不再进行函数调用。

2.使用内联函数时需要注意什么?

(1)在函数说明前要冠以关键字 " inline " ,如 :inline int max(int a,int b),表明max函数不是普通函数,是内联函数。

(2)内联函数在第一次被调用之前必须进行完整的定义,否则编译器将无法知道应该插入什么代码。

(3)在内联函数体内一般不能含有复杂的控制语句,如for语句、switch语句等等。

(4)通常只有规模很小而使用频繁的函数才定义为内联函数,当规模很大而且调用很频繁时,不但没有提高程序的运行速度反而增大了开销,这种情况下编译器会自动将其转换为普通函数处理。

 

作用域运算符::

1.为何C++要引入作用域运算符:: ?

如果有两个同名变量,一个是全局的,另一个是局部的,那么局部变量在其作用域内具有较高的优先权,它将屏蔽全局变量,这种情况下,如果想调用的是全局的同名变量,则需要在这个变量名前添加作用域运算符 :: 。

2.作用域运算符除了可以区分同名的全局变量和局部变量外,还有什么用处?

当我们需要用到C++的多文件程序时,尤其是类的声明和类构造函数、类成员函数定义分别放在.h头文件和.cpp源文件时,作用域运算符就起很大作用,在.cpp文件中定义类成员函数时必须要在类构造函数名或成员函数名前添加 作用域运算符 "::" 以让编译器可以区分这个函数究竟是属于哪一个类的。这是不同类中可以定义同名函数的关键。

 

运算符new和delete

1.C++中既然保留了malloc和free函数,为何还要引入new运算符和delete运算符?

new运算符可以根据数据类型自动计算所要分配内存的大小,而使用malloc函数时必须使用sizeof函数来计算所需要的字节数,这就减少了发生错误的可能性。此外,new运算符能够自动返回正确的指针类型,而malloc函数的返回值类型一律为void*,必须在程序中进行强制类型转换,才能使其指针指向具体的数据。

2.使用new和delete时需要注意的是什么?

(1)使用new可以为数组动态分配内存空间,这时需要在类型名后面缀上数组大小,如:int *p = new int[10]; 。

(2)new 可在为简单变量分配内存的同时进行初始化,初始值需放在圆括号内,如:int *p; p = new int(99); 。

(3)使用new动态分配内存时,如果没有足够的内存满足分配需求,则动态分配空间失败,编译系统会返回空指针NULL,因此在使用new动态分配内存时一般会搭配if条件语句对内存是否分配成功进行检测。

(4)用new分配的存储空间不会自动释放,只能通过delete释放。因此要在适当的时候释放动态分配的内存空间。当释放的是分配给数组的内存空间时,需要在指针变量名前加一个方括号,如: delete []pi; 。

 

引用

1.C++中为何要引入 “ 引用 ” ?其本质是什么?如何定义一个变量的引用?

引用的意义在于为变量另起一个名字,以便在需要时可以方便、间接地引用该变量。引用其实就是一个变量的别名,当定义了多个引用并且用同一个变量去初始化这些引用的时候代表这个变量有多个别名,不管有多少个引用,所有引用都代表同一个变量。定义一个变量的引用:int i = 5;int &j = i;这里要注意 “ & ” 是引用声明符,此时它不代表地址。

2.使用引用时需要注意的是什么?

(1)引用并不是一种独立的数据类型,它必须与某一种类型的变量相联系。在声明引用时,必须立即对它进行初始化,不能声明完成后再赋值。如:int i = 10; int &j; j = i; 这是错误的。

(2)为引用提供的初始值可以是一个变量也可以是另一个引用。如 int i = 5; int &j1 = i; int &j2 = j1; 这是合法的。

(3)指针是通过地址间接访问某个变量,而引用是通过别名直接访问某个变量。每次使用引用时,可以不用像指针那样书写间接运算符 " * ",因而使用引用比使用指针更直观、方便。

(4)引用在初始化后不能再被重新声明为另一个变量的引用(别名)。如:int i,k; int &j = i; j = &k; 这是错误的。

 

构造函数与析构函数

1.C++中的构造函数与析构函数分别有什么作用?

构造函数是一种特殊的成员函数,它主要用于为对象分配空间,进行初始化。 析构函数也是一种特殊的成员函数,它执行与构造函数相反的操作,通常用于撤销对象时的一些清理任务,如释放对象的内存空间等。

2.使用构造函数时需要注意的是什么?

(1)构造函数的名字必须与类名相同,不能由用户任意命名。

(2)构造函数是不仅可以不带参数,也可以自带默认的参数。

(3)构造函数没有返回值,在定义构造函数时,不能说明它的类型,即使是说明为void类型也是不行的。

(4)与普通的成员函数一样,构造函数的函数体可以写在类体内,也可以写在类外。与普通的成员函数一样,当构造函数直接定义在类内时,系统将构造函数作为内联函数处理。

(5)构造函数一般声明为公有成员,但它不需要也不能像其他成员函数那样被显式地调用,它是在定义对象的同时被自动调用的,而且只执行一次。

(6)构造函数的函数体是用户可以自行定义的,函数体中可以不仅可以对数据成员赋初值,还可以包含其它语句。

(7)构造函数可以重载,系统会根据用户调用时输入的参数进行判断到底调用的是哪一个构造函数。

(8)如果构造函数的函数体用户没有定义,则编译系统会自动地生成一个默认构造函数。

3.使用析构函数时需要注意的是什么?

(1)析构函数与构造函数的名字相同,但它前面必须加一个波浪号(~) 。

(2)析构函数没有参数。

(3)析构函数没有返回值。

(4)与普通的成员函数一样,析构函数的函数体可以写在类体内,也可以写在类外。与普通的成员函数一样,当析构函数直接定义在类内时,系统将析构函数作为内联函数处理。

(5)析构函数一般声明为公有成员,但它不需要也不能像其他成员函数那样被显式地调用,它是在撤销对象的同时被自动调用的,而且只执行一次。

(6)析构函数的函数体是用户可以自行定义的。

(7)析构函数不可以重载,一个类中只能有一个析构函数。

(8)如果析构函数的函数体用户没有定义,则编译系统会自动地生成一个默认析构函数。

(9)如果定义了一个全局对象,则在程序流程离开其作用域(如main函数结束或调用exit函数)时,调用该全局对象的析构函数。

(10)如果一个对象被定义在一个函数体内,则当这个函数被调用结束时,该对象应该释放,析构函数被自动调用。

(11)若一个对象是使用new运算符动态创建的,在使用delete运算符释放它时,delete会自动调用析构函数。

 

拷贝构造函数

1.拷贝构造函数有什么作用?

在建立一个新对象时,使用一个已经存在的对象去初始化这个对象就要用到拷贝构造函数。

2.如何定义一个拷贝构造函数?

3.使用拷贝构造函数时需要注意的是什么?

(1)拷贝构造函数也是一种构造函数,其函数名与类名相同,并且该函数没有返回值。

(2)拷贝构造函数只有一个参数,并且是同类对象的引用。

(3)每个类都必须有一个拷贝构造函数。程序员可以自定义拷贝构造函数,用于按照需要初始化对象。

(4)如果程序员没有定义类的拷贝构造函数,系统会自动生成一个默认的拷贝构造函数,用于复制出数据成员值完全相同的新对象。

 

自引用指针this

1.自引用指针this有何作用?

当定义了一个类的多个对象后,系统会为每一个对象分配存储空间。如果一个类包含了数据成员和成员函数,则系统会为这个类的多个对象的每一个数据成员都独立分配存储空间,但系统不会为这个类的多个对象的每一个成员函数都独立分配存储空间。因为多个对象所用的成员函数的代码是相同的,不论调用哪一个对象的成员函数,其实调用的都是相同内容的代码。所以C++的编译系统只用了一段空间来存放这个共同的函数代码段,在调用各对象的成员函数时,都去调用这个公用的函数代码。那么成员函数怎样辨别出当前调用自己的是哪个对象,从而对该对象的数据成员而不是其他对象的数据成员进行处理呢?原来,每当创立一个对象时,系统就把自引用指针this初始化为指向该对象,即this指针的值是当前调用成员函数的对象的起始地址。每当调用一个成员函数时,系统自动把this指针作为一个隐含的参数传给该函。不同的对象调用同一个成员函数时,C++编译器将根据成员函数的this指针所指向的对象来确定应该引用哪一个对象的数据成员,绝不会搞错。

 

string类

C++中引入string类有何意义?

C语言中,我们可以用字符数组或字符指针来存储一个字符串和调用标准字符串处理函数来对字符串进行处理,而C++仍保留了C语言中这一特点。为何C++还要引入字符串类呢?因为使用数组来存放字符串和调用标准字符串处理函数来处理字符串在使用的时候并不方便,而且数据与处理数据的函数分离也不符合面向对象方法的要求。因此C++中引入了更方便的字符串类型,string类。

 

static(静态)数据成员

C++中为何要引入静态数据成员?

在一个类中,若将一个数据成员说明为static,这种成员成为静态数据成员。与一般的数据成员不同,无论建立多少个类的对象,都只有一个静态数据成员的拷贝,实现了同一个类的不同对象之间的数据共享。

使用静态数据成员时应该注意的是什么?

(1)静态数据成员的定义与普通数据成员相似,但前面要加上 " static "关键字。

(2)静态数据成员的初始化与普通数据成员不同。静态数据成员初始化应在类外单独进行,而且应在定义对象之前进行。一般在main函数之前,类声明之后的特殊地带为它提供定义和初始化。

(3)静态数据成员属于类,而不像普通数据成员那样属于某一对象,因此可以使用 " 类名 :: "访问静态的数据成员。

(4)静态数据成员与静态变量一样,是在编译时创建并初始化的。它在该类的任何对象被建立之前就存在。因此,公有的静态数据成员可以在对象定义之前被访问,对象定义之后,公有的静态数据成员也可以通过对象进行访问。

(5)在类外,私有静态数据成员不能直接访问,必须通过公有的成员函数或友元函数访问。

(6)C++支持静态数据成员的一个主要原因是不必使用全局变量。依赖于全局变量的类几乎都是违反面向对象程序设计的封装特性的。静态数据成员的主要用途是定义类的所有对象公用的数据。

 

static(静态)成员函数

1.C++中为何要引入静态成员函数?

C++中不会用属于某个对象的成员函数来处理属于类的静态数据成员。那么C++中必须引入与静态数据成员配套的,专门用于处理静态数据成员、属于类的静态成员函数。

2.使用静态成员函数时需要注意的是什么?

(1)一般情况下,静态成员函数主要用来访问静态数据成员。当它与静态数据成员一起使用时,达到了对同一个类中对象之间共享数据的目的。

(2)一般而言,静态成员函数不访问类中的非静态数据成员。若确实需要,静态成员函数只能通过对象名或对象指针或对象引用访问该对象的非镜头成员。

(3)可以在建立对象之前就调用静态成员函数来处理静态数据成员,这是普通成员函数不能实现的功能。

(4)编译系统将静态成员函数限定为内部连接,也就是说,与现行文件相连接的其他文件中的同名函数不会与该函数发生冲突,维护了该函数使用的安全性。

(5)静态成员函数属于类,不属于某一对象。在类外调用公有的静态成员函数时,使用 " 类名 :: "调用。

 

友元函数

1.C++中为何引入友元函数?

类的主要特点之一是数据隐藏和封装,即类的私有成员只能在类定义的范围内使用(私有成员只能通过它的成员函数来访问)。但是,有时为了访问类的私有成员而需要在程序中多次调用成员函数,而频繁调用则会带来较大的时间和空间开销,降低程序的运行效率。为此,C++引入了友元函数,它可以访问该类的所有成员,包括私有成员、保护成员、公有成员。

2.使用友元函数时需要注意的是什么?

(1)友元函数既可以是不属于任何类的非成员函数,也可以是另一个类的成员函数。

(2)在类中声明友元函数时,需在其函数名前加上关键字friend。此声明可以放在公有部分、保护部分、私有部分。

(3)友元函数可以定义在类的内部,也可以定义在类的外部。

(4)在类的外部定义友元函数时,不必像成员函数那样在函数名前加上 " 类名 :: "

(5)因为友元函数不是类的成员,所以它不能直接访问对象的数据成员,也不能通过this指针访问对象的数据成员,它必须通过作为入口参数传递进来的对象名或对象指针或对象引用来访问该对象的数据成员。

(6)为了不与面向对象的程序设计思想背道而驰,应尽量减少友元函数的使用,使用友元函数时需谨慎。

 

友元类

1.C++中为何要引入友元类?

当一个类中含有多个属于另一个类的成员函数的友元函数时,可以直接把另一个类定义为这个类的友元类,这样可以使另一个类的所有成员函数都成为这个类的友元函数。

2.使用友元类时需要注意的是什么?

(1)友元类的声明可以放在类中的公有部分、私有部分、保护部分。

(2)友元关系是单向的,不具有交换性。若声明了类X是类Y的友元,不等于类Y一定是类X的友元,这要看类X中是否有相应的声明。

(3)友元关系不具有传递性。若类X是类Y的友元,类Y是类Z的友元,不一定类X是类Z的友元。如果想让类X是类Z的友元类,应在类Z中作出声明。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值