C++,关键字NULL使用之前必须声明一个类必须使用关键字吗

为了便于温故而知新特于此整悝 C/C++ 方面相关面试题。分享共勉。

(备注:各题的重要程度与先后顺序无关不断更新中......欢迎补充)

(1)分析下面程序的输出(* 与 -- 运算符優先级问题)

(2)指针函数与函数指针的区别

指针函数是指一个返回指针类型的函数。函数指针是指一个指向函数的指针

(3)函数模板與模板函数的区别

函数模板指由关键字template、typename(或class)定义的通用函数体。

将类型形参实例化的参数成为模板实参模板函数指用模板实参实例囮的函数。

即模板函数指将函数模板的类型形参实例化的过程

第一、修饰局部变量。static修饰的局部变量只执行一次初始化且延长了局部變量的生命周期,直到程序运行结束以后才释放

  static修饰的局部变量存放在全局数据区的静态变量区。初始化的时默认值为0;

第二、修飾全局变量static修饰的全局变量只能在本文件中访问,不能在其它文件中访问即便是加extern外部声明一个类必须使用关键字也不可以。

第三、修饰函数若static修饰一个函数,则这个函数的只能在本文件中调用不能在其他文件被调用。即具有文件作用域

第一、类中静态成员分为 靜态成员变量 和 静态成员函数。

第二、静态成员变量的名字在类的作用域中可以避免命名冲突。

第三、静态成员变量独立于该类的任何對象而存在

第四、静态成员变量可以声明一个类必须使用关键字为任意类型:常量、引用、数组、类本身类型等。

第五、静态成员变量必须在类的定义体外部初始化值

第六、静态成员函数与一般普通成员函数最大的区别在于不存在this指针。因为这个函数是与类相关的函数而不是与某一个对象相关。

第七、声明一个类必须使用关键字静态成员函数时在前面加关键字static当在类外实现这个函数时,不允许加关鍵字

第八、可以通过作用域操作符直接调用static静态成员函数。或通过类的对象、引用或指向类对象的指针间接的调用static静态成员函数

第九、static静态成员函数不是任何对象的组成部分,所以static成员函数不能被声明一个类必须使用关键字为const

  (函数声明一个类必须使用关键字为const昰对函数this指针的进一步限定,而static成员函数本身就不存在this指针所以再加const是没有意义。)

第十、static静态成员函数不可以被声明一个类必须使用關键字为虚函数虚函数是为实现多态的一种特殊成员函数,因为static函数没有this指针因此是没有意义的。

(5)相比于C函数C++函数有哪些特色?

C++函数增加重载、内联、const、virtual四种新机制

重载和内联机制既可以用于全局函数也可以用于类的成员函数。

const和virtual机制仅用于类的成员函数

(6)重载、覆盖、隐藏的区别

重载是指在同一个类中,同名函数参数不同。重载的核心在于参数参数有三个基本点:1、类型  2、数量  3、顺序。(切记与返回值无关)

注意:第一、作用域(全局函数与类中成员函数同名不算重载)。第二、类中成员函数加const修饰也算作重载范疇

覆盖是指派生类重写(遵循三同原则)基类的虚函数。

一则:派生类与基类的函数同名但参数不同,与关键字virtual无关;(不同于重载)

二则:派生类与基类的函数同名并且同参,但无关键字virtual;(不同于覆盖)

(7)函数strlen与操作符sizeof的区别:参见随笔《》

(8)函数声明一个類必须使用关键字声明一个类必须使用关键字函数原型时,函数每个形参的名称可省略主要声明一个类必须使用关键字清楚每个参数嘚类型和返回值类型就可以了。

(9)表达式所有的表达式都有值。

(10)编译程序的编译是以文件为单位的,因此将程序分到多个文件Φ可以减少每次对程序修改后再编译所带来的工作量

(11)静态成员变量。类的静态数据成员变量需要在类定义外进行初始化

(12)友元。当将一个类S定义为另一个类A的友元类时类S的所有成员函数都可以直接访问类A的所有成员(成员变量和成员函数)。

(13)C/C++内存分配区别:

2、都是在堆(heap)上进行动态的内存操作

3、用malloc函数需要指定内存分配的字节数并且不能初始化对象;new 会自动调用对象的构造函数。

(14)洳果创建的是静态局部或全局对象则对象的位模式全部为0,否则默认值将会是随机的

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

(16)类中成员对象的构造是按照在类中萣义的顺序进行的,而不是按照构造函数冒号后的初始化列表顺序进行构造的(这点尤其需要注意)

(17)explicit关键字。普通构造函数可以被隱式调用而被关键字explicit修饰的构造函数只能被显式调用。

(18)拷贝构造函数使用情况:

1、一个对象以值传递的方式传入函数体

2、一个对潒以值传递的方式从函数返回。

3、一个对象需要通过另外一个对象进行初始化

(19)在ANSI C 语言中用什么来定义常量呢?答案是enum类型和#define宏这兩个都可以用来定义常量。而在C++的类中实现常量需要考虑使用枚举。

(20)一个类的构造和析构函数都不能用const修饰

(21)const修饰成员函数。const茬类中对成员函数的三种作用(1、参数;2、返回值;3、函数体)

2、默认的,第一个枚举成员赋值为0后面的每个枚举成员的值比前面的夶1。

3、枚举成员本身是一个常量表达式不可以改变其值。

4、可以显式的定义枚举成员的值当随机指定其中某个成员值后,位于其前的荿员值仍为默认值位于其后的成员值比前面的大一。

(23)引用与指针的区别

1、初始化要求不同前者必须要初始化。

2、可修改性不同湔者一旦被初始化,它就不能被另一个对象引用而指针在任何时候都可以指向另一个对象。

3、不存在NULL引用引用必须要确定具体引用的昰某个对象。

4、测试的区别引用不会指向空值,使用引用前不需要测试它的合法性指针可能为空值,使用前需要进行测试避免空指針导致程序崩溃。

5、应用的区别如果指向一个对象后就不会再改变指向,那么选择使用引用如果在不同的时刻需要指向不同的对象,應该使用指针

(24)内联是以代码膨胀为代价的,仅仅省去了函数调用的开销从而提高了函数的执行效率,一般适合于使用频率高并苴代码量简单的函数。

(25)内联与宏的区别

内联函数在编译时展开宏在预编译时展开。

在编译时内联函数可以直接被嵌入到目标代码Φ而宏在预处理是只是仅仅的文本替换。

内联函数可以完成类型匹配语句正确的判断,而宏不具有

宏不属于函数,内联函数属于函數

宏在定义时要小心处理宏参数,以免出现二义性

(26)头文件中的ifndef/define/endif干什么用?防止头文件被重复引用

1、const即“只读”。可以定义 const 常量

2、const可以修饰成员函数的参数、返回值,甚至函数的定义体

被const 修饰的东西都受到强制保护,可以预防意外的变动能提高程序的健壮性。

(29)在C++ 程序中调用被 C 编译器编译后的函数为什么要加 extern “C”?

C++语言支持函数重载C 语言不支持函数重载。函数被C++编译后在库中的名字与C 語言的不同假设某个函数的原型为:

C++提供了C 连接交换指定符号extern“C”来解决名字匹配问题。

(30)内存思考题1代码如下:

请问运行Test 函数会囿什么样的结果?

程序崩溃因为GetMemory 并不能传递动态内存,

(31)内存思考题2代码如下:

请问运行Test 函数会有什么样的结果?

因为GetMemory 返回的是指姠“栈内存”的指针该指针的地址不是 NULL,

但其原来的内容已经被清除新内容不可知。

(32)内存思考题3代码如下:

请问运行Test 函数会有什么样的结果?

(33)内存思考题4代码如下:

请问运行Test 函数会有什么样的结果?

篡改动态内存区的内容后果难以预料,非常危险

(34)铨局变量和局部变量有什么区别?怎么实现的操作系统和编译器是怎么知道的?

全局变量的生命周期是整个程序运行期间而局部变量嘚生命周期则是局部函数或过程调用的时间段。

其实现是由编译器在编译时采用不同内存分配方法

全局变量在main函数调用前,就开始分配如果是静态变量则是在main函数前就已经初始化了。而局部变量则是在用户栈中动态分配的

(35)C语言文件读写程序

下面这个程序执行后会囿什么错误或者效果:

Stack的空间由操作系统自动分配/释放,Heap上的空间手动分配/释放

Stack空间有限,Heap是很大的自由存储区

C中的malloc函数分配的内存空间即在堆上C++中对应的是new操作符。

程序在编译期对变量和函数分配内存都在栈上进行,且程序运行过程中函数调用时参数的传递也在栈上进行

(40)请定义一个宏,比较两个数的a、b的大小不能使用大于、小于、if语句。

(41)交换两个数的方法参见随笔《》

(42)设置或者清除某位。参见随笔《》

(43)求最大字段和参见随笔《》

(44)字节对齐。参见随笔《》

(45)大小端判断参见随笔《》

(46)查找数组中的最小囷次小项。参见随笔《》

(47)用预处理指令#define 声明一个类必须使用关键字一个常数用以表明1年中有多少秒(忽略闰年问题)。

1、 #define 语法的基夲知识(例如:不能以分号结束括号的使用等等)。

2、 懂得预处理器将为你计算常数表达式的值因此,直接写出你是如何计算一年中囿多少秒而不是计算出实际的值是更清晰而没有代价的。

3、 意识到这个表达式将使一个16位机的整型数溢出-因此要用到长整型符号L告诉編译器这个常数是的长整型数。

4、 如果你在你的表达式中用到UL(表示无符号长整型)那么你有了一个好的起点。记住第一印象很重要。

(48)用变量a给出下面的定义

g) 一个指向函数的指针该函数有一个整型参数并返回一个整型数

h) 一个有10个指针的数组,该指针指向一个函数该函数有一个整型参数并返回一个整型数

(49)关键字typedef 与 宏的区别。参见随笔《》

(50)如何引用一个已经定义过的全局变量

可以用引用頭文件的方式,或者可以用extern关键字

如果用引用头文件方式来引用某个在头文件中声明一个类必须使用关键字的全局变量,假定你将那个變量写错了那么在编译期间会报错。

如果你用extern方式引用时假定你犯了同样的错误,那么在编译期间不会报错而在链接期间报错。

(51)全局变量和局部变量在内存中有什么区别

全局变量储存在静态数据区,局部变量在堆栈中

(54)堆栈溢出一般是由什么原因导致的?

(55)什么函数不能声明一个类必须使用关键字为虚函数

(56)不能做switch()的参数类型是:

switch的参数不能为实型。

(57)局部变量能否和全局变量重洺

能,局部会屏蔽全局要用全局变量,需要使用"::"

局部变量可以与全局变量同名在函数内引用这个变量时,会用到同名的局部变量洏不会用到全局变量。

对于有些编译器而言在同一个函数内可以定义多个同名的局部变量,比如在两个循环体内都定义一个同名的局部變量而那个局部变量的作用域就在那个循环体内。

(58)全局变量可不可以定义在可被多个.C文件包含的头文件中为什么?

可以在不同嘚C文件中以static形式来声明一个类必须使用关键字同名全局变量。

可以在不同的C文件中声明一个类必须使用关键字同名的全局变量前提是其Φ只能有一个C文件中对此变量赋初值,此时链接不会出错

前一个循环一遍再判断,后一个判断以后再循环

(60)语句for( ;1 ;)有什么问题?咜是什么意思

无限循环,和while(1)相同

(61)写出下面程序的输出内容

(62)写出下列代码的输出内容

分析:DATE是一个union, 变量共用空间,里面最大的變量类型是int[5], 占用20个字节所以它的大小是20。

(63)写出下列代码的输出内容

(64)找出下面代码中的所以错误(下面为正常标准程序)

说明:鉯下代码是把一个字符串倒序如“abcd”倒序后变为“dcba”

16 free(dest);// 使用完,应当释放空间以免造成内存泄露

(65)对于一个频繁使用的短小函数,在C語言中应用什么实现在C++中应用什么实现?

C语言用宏定义,C++用inline实现

(66)下面的程序是否有错误,如果有错请说明原因。

因为pszHelp指向一个常量字符串所以根本不允许修改字符串内容。除非使用一个字符数组

包含抽象函数的类是抽象类,满足virtual fun() = 0; 的语法的函数是抽象函数主要鼡于提供接口。

(68)什么时候需要使用虚析构函数

一般情况下类的析构函数都定义成虚函数,主要是考虑在使用基类指针操作派生类对潒时保证类的析构顺序

(69)请指出下面代码存在的潜在问题

(70)请写出下列程序运行的结果

(71)Debug版本中经常使用ASSERT进行断言,在Release版本中有┅个起同样作用的函数请说明。

(72)描述内存分配方式以及它们的区别?

1) 从静态存储区域分配内存在程序编译的时候就已经分配好,這块内存在程序的整个运行期间都存在例如全局变量,static 变量

2) 在栈上创建。在执行函数时函数内局部变量的存储单元都可以在栈上創建,函数执行结束时这些存储单元自动被释放栈内存分配运算内置于处理器的指令集。

3) 从堆上分配亦称动态内存分配。程序在运荇的时候用malloc 或new 申请任意多少的内存程序员自己负责在何时用free 或delete 释放内存。

动态内存的生存期由程序员决定使用非常灵活。

(73)C++四种类型转换方式

关于各种方式区别参见随笔《》

(74)类成员函数的重载、覆盖和隐藏区别

a、成员函数被重载的特征:

  1、相同的范围(在哃一个类中);

  2、函数名字相同;

  4、virtual 关键字可有可无。

b、覆盖是指派生类函数覆盖基类函数特征是:

  1、不同的范围(分别位于派生类与基类);

  2、函数名字相同;

  4、基类函数必须有virtual 关键字。

c、“隐藏”是指派生类的函数屏蔽了与其同名的基类函数規则如下:

  1、如果派生类的函数与基类的函数同名,但是参数不同此时,不论有无virtual关键字基类的函数将被隐藏(注意别与重载混淆)。

  2、如果派生类的函数与基类的函数同名并且参数也相同,但是基类函数没有virtual关键字此时,基类的函数被隐藏(注意别与覆蓋混淆)

(75)如何打印出当前源文件的文件名以及源文件的当前行号?

__FILE__和__LINE__是系统预定义宏这种宏并不是在某个文件中定义的,而是由編译器定义的

(76)main 函数执行以前,还会执行什么代码

全局对象的构造函数会在main 函数之前执行。

(77)main 主函数执行完毕后是否可能会再執行一段代码,给出说明

可以,可以用_onexit 注册一个函数它会在main 之后执行。示例代码如下:

(78)如何判断一段程序是由C 编译程序还是由C++编譯程序编译的

(79)写出下列程序的输出内容

(80)写出下列程序的输出内容

(81)写出下列程序的输出内容

29 //执行结束 p指向C 但是str[0]指向D后面的元素,因此内容为空 31 //执行结束 p指向C不变 str[1]指向p后一个元素的地址即就是D

(82)C++中虚函数和纯虚函数的区别? 

1、声明一个类必须使用关键字的差異纯虚函数的声明一个类必须使用关键字除过像虚函数加关键字virtual而外,还必须加 = 0;

声明一个类必须使用关键字为虚函数的作用是为了能让這个函数在它的派生类里面被覆盖或隐藏这样编译器就可以使用后期绑定来达到多态性。

声明一个类必须使用关键字纯虚函数有一种接口的规范作用。派生类必须且只能原样实现

2、定义的差异。虚函数在基类中必须实现(哪怕空操作)派生类里面也可以不覆盖或隐藏。但纯虚函数必须在派生类里面去实现

3、虚基类或抽象类。带纯虚函数的类叫做虚基类或抽象类。这种基类不能直接声明一个类必須使用关键字对象只能被继承,并且只有在实现其纯虚函数后才能使用

(83)什么时候需要“引用”?

流操作符<< 和 >>、赋值操作符=的返回徝、拷贝构造函数的参数、赋值操作符=的参数、其它情况都推荐使用引用

(84)结构与联合的区别?

1. 结构和联合都是由多个不同的数据类型成员组成

但在任何同一时刻, 联合中只存放了一个被选中的成员(所有成员共用一块地址空间), 而结构的所有成员都存在(不同成员的存放地址不同)。

2. 对于联合的不同成员赋值, 将会对其它成员重写,  原来成员的值就不存在了, 而对于结构的不同成员赋值是互不影响的

(85)丅列关于联合的程序输出

低位低地址,高位高地址内存占用情况是Ox010A

都是在堆(heap)上进行动态的内存操作。用malloc函数需要指定内存分配的字节数並且不能初始化对象new 会自动调用对象的构造函数。

关于new 和 delete详情内容请参见随笔《》

(87)C++是不是类型安全的

不是。两个不同类型的指针の间可以强制转换(用reinterpret cast)C#是类型安全的。

(88)当一个类A中没有生命任何成员变量与成员函数,这时sizeof(A)的值是多少如果不是零,请解释一下编譯器为什么没有让它为零

肯定不是零。举个反例如果是零的话,声明一个类必须使用关键字一个class A[10]对象数组而每一个对象占用的空间昰零,这时就没办法区分A[0],A[1]…了

(89)简述数组与指针的区别?

数组要么在静态存储区被创建(如全局数组)要么在栈上被创建。指针可鉯随时指向任意类型的内存块

1、复制的内容不同。strcpy仅仅复制字符串而memcpy可以复制任何类型的数据内容

2、复制的方法不同。strcpy不需要指定长喥它遇到字符串结束符"\0"便结束。memcpy则是根据其第三个参数决定复制的长度

3、用途不同。通常在复制字符串时用strcpy而复制其它类型数据时┅般用memcpy()

(91)写出下列程序的输出内容:

(92)写出下列程序的输出内容:

(int*)* 相当于没有进行任何操作,所以等同于:

这里先取b的地址然后把哋址转换成int*,之后+i是指针算术也就是在b的地址上加一个int的长度。

最后前面的*是解指针,这段最后返回的是“b的地址 + i个int长度”的地址值

最前面的(Fun)是强制把“b的地址 + i个int长度”的地址值转换为一个“没有参数,返回void类型的函数指针”

所以pFun就是一个函数指针,其指向的位置從一开始的b的地址每次循环加一个int类型的长度。

然后我们来看实际情况:

并把它转换为Fun类型,也就是一个没有参数返回void类型的函数指针,所以最后得到的就是一个函数指针

再来看循环,循环3次pFun变量分别被赋了3次值,每次都是一个函数指针

由于Base类型中有virtual虚函数,所以b的地址指向的是b的vtbl(虚函数表),vtbl虚函数表可以看作是一个保存了函数指针的数组

那么后两次就指向Base::fun2 和 Base::fun3了。编码以明志调试而致远。调试结果如下:

至于为什么是按照这样的顺序排列的因为其声明一个类必须使用关键字顺序。

(93)写出下列程序的输出内容

(94)在什麼时候需要使用“常引用” 

如果既要利用引用提高程序的效率,又要保护传递给函数的数据不在函数中被改变就应使用常引用。

常引用声明一个类必须使用关键字方式:const 类型标识符 & 引用名 = 目标变量名;

(95)流操作符重载返回值申明为“引用”的作用:

流操作符< <和>>这兩个操作符常常希望被连续使用,例如:cout << "hello" << endl; 因此这两个操作符的返回值应该是一个仍然支持这两个操作符的流引用

可选的其它方案包括:返回一个流对象和返回一个流对象指针。

但是对于返回一个流对象程序必须重新(拷贝)构造一个新的流对象,也就是说连续的两個<<操作符实际上是针对不同对象的!

这无法让人接受。对于返回一个流指针则不能连续使用<<操作符因此,返回一个流对象引用是惟一选擇

这个唯一选择很关键,它说明了引用的重要性以及无可替代性也许这就是C++语言中引入引用这个概念的原因吧。赋值操作符=

这个操莋符象流操作符一样,是可以连续使用的例如:x = j = 10; 或者 (x = 10) = 100;赋值操作符的返回值必须是一个左值,以便可以被继续赋值

因此引用成了这个操莋符的惟一返回值选择。

(96)系统为变量赋的默认值打印结果:(系统:win32 + VS2010)

注意:系统不会为局部变量赋默认值因此直接打印局部变量嘚默认值导致崩溃!

类中含有const、reference 成员变量;基类的构造函数都需要初始化表。

(98)面向对象的三个基本特征并简单叙述之?

2、继承:广義的继承有三种实现形式:

实现继承(指使用基类的属性和方法而无需额外编码的能力)、

可视继承(子窗体使用父窗体的外观和实现代碼)、

接口继承(仅使用属性和方法实现滞后到子类实现)。前两种(类继承)和后一种(对象组合 => 接口继承以及纯虚函数)构成了功能复用的两种方式

3、多态:是将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后父对象就可以根据当前赋值给它的孓对象的特性以不同的方式运作。

简单的说就是一句话:允许将子类类型的指针赋值给父类类型的指针。

(99)找出下列代码的问题:

如果面试者指出字符数组str1不能在数组内结束可以给3分;

如果面试者指出strcpy(string, str1)调用使得从str1内存起复制到string内存起所复制的字节数具有不确定性可以给7汾在此基础上指出库函数strcpy工作方式的给10 分;

扫描s2指向的内存,逐个字符付到s1所指向的内存直到碰到'\0',因为str1结尾没有'\0'。所以具有不确定性不知道他后面还会赋值什么东东。

(100)C++中为什么用模板类

1、可用来创建动态增长和减小的数据结构。

2、它是类型无关的因此具有很高的可复用性。

3、它在编译时而不是运行时检查数据类型保证了类型安全。

4、它是平台无关的可移植性。

5、可用于基本数据类型

不昰,其它数据类型转换到CString可以使用CString的成员函数Format来转换

(102)函数模板与类模板有什么区别

函数模板的实例化是由编译程序在处理函数调用時自动完成的,而类模板的实例化必须由程序员在程序中显式地指定

(103)动态连接库的两种方式?

调用一个DLL中的函数有两种方法:

1、载入時动态链接(load-time dynamic linking),模块非常明确调用某个导出函数使得他们就像本地函数一样。

这需要链接时链接那些函数所在DLL的导入库导入库向系統提供了载入DLL时所需的信息及DLL函数定位。

DLL载入后模块可以通过调用GetProcAddress获取DLL函数的出口地址,然后就可以通过返回的函数指针调用DLL函数了

(104)类中函数详解(构造函数、析构函数、拷贝构造函数、赋值构造函数)。请参见随笔《》

(105)写出下列程序编译错误问题的原因

13 p2++; // OK 宏定義仅仅只是文本替换其本质与p1相同。可以编译通过

(106)“引用”与多态的关系

引用是除指针外另一个可以产生多态效果的手段。这意菋着一个基类的引用可以指向它的派生类实例。

(107)多态的作用

1、 隐藏实现细节,使得代码能够模块化;扩展代码模块实现代码重鼡;

2、 接口重用:为了类在继承和派生的时候,保证使用家族中任一类实例的某一属性时的正确调用

(108)STL中容器map,map有几种赋值方式每種方式有何区别?

(109)STL中容器list使用list容器的merge方法需要注意什么?

(110)介于vector和list之间的一种容器deque请参见随笔《》

(111)C++语言中如何访问一个类私有成员变量?

两种方式第一,接口利用访问成员变量相应的set/get公共成员函数;第二,友元友元类和友元函数。

(112)由于本文篇幅太長编辑后保存太慢。下面续《 》

顺序 选择 循环 总结

  • 数据成员一般声明一个类必須使用关键字为private以实现信息的隐蔽
  • 成员函数一般声明一个类必须使用关键字为public,以提供外界使用的接口
  • 构造函数一般声明一个类必须使鼡关键字为public以便创建类的对象

  • 创建一个类类型的对象时,编译器会自动使用一个构造函数来初始化该对象构造函数是一个特殊的、与類同名的成员函数,用于初始化每个数据成员来设置初始值

  • 构造函数一般使用一个构造函数初始化列表,来初始化对象的数据成员

    • 构造函数初始化列表由成员名和带括号的初始值组成跟在构造函数的形参表之后,并以冒号开头
  • 在类内部,声明一个类必须使用关键字成員函数是必需的而定义成员函数则可选,可以在类外定义在类内部定义的函数默认为inline 函数

-在类外部定义的成员函数必须指明它们是在類的作用域中。

  • 将关键字const 加在形参表之后就可以将成员函数声明一个类必须使用关键字为常量,const成员不能改变其所操作的对象的数据成員const 必须同时出现在声明一个类必须使用关键字和定义中!!!!

  • 用struct关键字和class关键字定义的类区别:

  • 对于一个空类,编译器默认产生4个成員函数:默认构造函数、析构函数、拷贝构造函数和赋值函数(13/14章)(p104面试宝典)

  • 因为static成员不是任何对象的组成部分所以static成员函数不能聲明一个类必须使用关键字为const.毕竟,将成员函数声明一个类必须使用关键字为const就是承若不会修改该函数所属的对象最后,static成员函数也不能声明一个类必须使用关键字为虚函数(15.2.4)(12.6节)

  • 声明一个类必须使用关键字为const的成员函数是没法修改数据成员的,这时候我们可以把數据成员声明一个类必须使用关键字为mutable类型这样就可以修改了。

  • 私有的mutable类型数据成员任然是无法通过对象直接的,还是需要成员函数來访问的(12.2)

  • 在C++中,用类来定义自己的抽象数据类型通过定义类型来对应所要解决的问题中的各种概念,可以更加容易编写、调试和修改程序

  • 12 章 : 类作用域、构造函数以及this 指针、友元、可变成员和静态成员

  • 从第1章开始,我们就已经开始使用类标准库类型:vector、istream、string都是类類型。 还有自己定义的Sale_item 类

  • 类就是定义了一个新的类型和一个新的作用域。

  • 对于一个空类编译器默认产生4个成员函数:默认构慥函数、析构函数、拷贝构造函数和赋值函数(13/14章)(p104面试宝典)

1、类成员—-所有成员必须在类内部声明一个类必须使用关键字,一旦类定义完成后就没有别的方式增加荿员了

  • 每个类可以没有成员,也可以定义多个成员成员可以是数据和函数或类型别名

    • 一个类可以包含若干公有的、私有的和受保护的部汾。public、private、protected

    • 所有成员必须在类内部声明一个类必须使用关键字一旦类定义完成后,就没有别的方式增加成员了

    • 数据成员一般声明一个类必须使用关键字为private,以实现信息的隐蔽

    • 成员函数一般声明一个类必须使用关键字为public以提供外界使用的接口
    • 构造函数一般声明一个类必须使用关键字为public,以便创建类的对象

2、构造函数—-与类同名的成员函数用于初始化每个数据成员来设置初始值。

  • 创建一个类类型的对象时编译器会自动使用一个构造函数来初始化该对象,构造函数是一个特殊的、与类同名的成员函数用于初始化每个数据成员来设置初始值。

  • 构造函数一般使用一个构造函数初始化列表来初始化对象的数據成员

    -构造函数初始化列表由成员名和带括号的初始值组成,跟在构造函数的形参表之后并以冒号开头。


 

3、成员函数—-必须在类内声明一个类必须使用关键字但可以在类外定义,茬类内定义的默认为inline函数

 
 
  • 在类内部声明一个类必须使用关键字成员函数是必需的,而定义成员函数则可选可以在类外定义。在类内部萣义的函数默认为inline 函数
 
-在类外部定义的成员函数必须指明它们是在类的作用域中
  • 成员函数都有一个隐含的实参,将函数绑定到调用函数嘚对象当我们编写函数 trans.avg_price()时,就是在调用名为trans的对象的avg_price函数如果trans是一个Sale_item对象,则在avg_price函数内部对Sale_item类成员的引用就是对trans成员的引用

  • 将关键芓const 加在形参表之后,就可以将成员函数声明一个类必须使用关键字为常量const成员不能改变其所操作的对象的数据成员。const 必须同时出现在声奣一个类必须使用关键字和定义中!!!!

  • 虽然声明一个类必须使用关键字为const的成员函数是没法修改数据成员的这时候我们可以把数据荿员声明一个类必须使用关键字为mutable类型,这样就可以修改了
  • 私有的mutable类型数据成员,任然是无法通过对象直接的还是需要成员函数来访問的。(12.2)

  • 因为static成员不是任何对象的组成部分所以static成员函数不能声明一个类必须使用关键字为const.毕竟,将成员函数声明一个类必须使用关鍵字为const就是承若不会修改该函数所属的对象最后,static成员函数也不能声明一个类必须使用关键字为虚函数(15.2.4)

 
  • 用struct关键字和class关键字定义的類区别:

 

 
  • 类背后的思想是数据抽象和封装

  • 数据抽象是一种依赖于接口和实现分离的技术,使用该类的程序员不必了解这些细节他们只需要考虑该类型做什么而不需要考虑该类型如何工作。

  • 封装是一项将低层次的元素组合起来形成新的、高层次实体的技术函数是封装的一种形式,函数所执行的细节行为被封装在函数本身这个更大的实体中被封装的元素隐藏了它们的实现细节——可以调鼡一个函数但不能访问它所执行的语句。同样地类也是一个封装的实体:它代表若干成员的聚集,大多数(良好设计的)类类型隐藏了實现该类型的成员

  • 标准库类型vector同时具备数据抽象和封装的特性,在使用方面是抽象的只需考虑他的接口,即执行的操作但它又是封裝的,因为我们既无法了解该类型如何表示的细节也无法访问其任意的实现制品。另一方面数组概念类似于vector,但既不是抽象的也不昰封装的。

 

 
  • 在c++中使用访问标号来定义类的抽象接口和实施封装。一个类可以没有访问标号也可以包含多个访問标号:
    • 程序所有部分都可以访问带有public 标号的成员。类型的数据抽象视图由其public成员定义;
    • 使用类的代码不可以访问带有private标号成员private封装了類型的实现细节。
 
-一个访问标号可以出现的次数没有限制每个访问标号指定了随后的成员定义的访问级别。这个指定的访问级别持续有效直到遇到下一个访问标号或看到类定义体的右花括号为止。
-可以在任意的访问标号出现之前定义类成员在类的左花括号之后、第一個访问标号之前定义成员的访问级别,其值依赖于类是如何定义的如果类是用struct关键字定义的,则在第一个访问标号之前的成员是公有的:如果类时用class关键字定义的则这些成员私有。
  • 如果类中某成员的定义之前没有出现任何访问标号则在用class定义的类中,成员默认为private成员struct 关键字定义的类中,成员默认为public成员

  • 并非所有类型都必须是抽象的标准库中的pair类就是一个实用的、设计良好的具体类而不是抽象类,具体类会暴露而非隐藏其实现细节

  • 一些类,例如pair 确实没有抽象接口。pair类型只是将两个数据成员酷捆绑成单个对象在这种情况下,隐藏数据成员没有必要
  • 这样的类型通常还有成员函数,特别的如果类具有内置类型或复合类型数据成员,那么定义构造函数来初始化这些成员就是一个好主意
 

2、编程角色的不同类别

 
 

3、数据抽象和封装的好处

 
 
  • 数据抽象和封装提供叻两个优点:
    • 避免类内部出现无意的、可能破坏对象状态的用户级错误。
    • 随时间推移可以根据需求改变或缺陷报告来完善类实现而无须妀变用户级代码。
  • 改变头文件中的类定义可以有效地改变包含该头文件的每个源文件的程序文本所以,当类发生改变时使用该类的代碼必须重新编译

版权声明一个类必须使用关键字:本文为博主原创文章未经博主允许不得转载。 /u/article/details/


在C++中类的静态成员(static member)必须在类内声明一个类必须使用关键字,在类外初始化像下媔这样。

为什么因为静态成员属于整个类,而不属于某个对象如果在类内初始化,会导致每个对象都包含该静态成员这是矛盾的。

能在类中初始化的成员只有一种那就是静态常量成员。

  • 静态常量数据成员可以在类内初始化(即类内声明一个类必须使用关键字的同时初始化)也可以在类外,即类的实现文件中初始化不能在构造函数中初始化,也不能在构造函数的初始化列表中初始化;
  • 静态非常量数据荿员只能在类外即类的实现文件中初始化,也不能在构造函数中初始化不能在构造函数的初始化列表中初始化;
  • 非静态的常量数据成員不能在类内初始化,也不能在构造函数中初始化而只能且必须在构造函数的初始化列表中初始化;
  • 非静态的非常量数据成员不能在类內初始化,可以在构造函数中初始化也可以在构造函数的初始化列表中初始化;

类型 初始化方式

 以下三种类型必须通过初始化列表来初始化


3. 没有默认构造函数的类类型

我要回帖

更多关于 声明一个类必须使用关键字 的文章

 

随机推荐