分享

C++基础概念

 vclyin 2009-12-03

  [参考书籍]  C++语言程序设计教程  作者:宋斌 曾春平 朱小谷
 
Ø 
const

const定义常量和#define定义常量的区别

1、const常量有数据类型,而宏常量没有数据类型

2、有些集成化的调试工具可以对const常量进行调试,但不能对宏常量进行调试。

强烈建议在C++程序中使用const常量而不使用宏常量。

Ø  存储类

1、auto(自动的)

auto变量是用堆栈方式占用内存空间的,担当程序执行到变量所属段外时,内存立即回收。

2、register(寄存的)

声明register变量,它告诉编译器,如果可能则将此变量保存在寄存器中,可以加快程序的速度。

3、static(静态的)

C++中用固定的地址来保存静态变量。只要程序在运行,静态变量就不会随着运行段的结束而消失。定义静态变量必须进行初始化。

4、extern(外部的)

外部变量的作用域是程序级的。即当一个变量被定义为外部变量后,该程序中其他所有的函数或程序段都可以引用这个变量。由于它具有可同时被其他函数引用的特性,而且在程序运行期间永不消失,因此可以用来在函数之间传递数据。

Ø  typedef

用来自定义数据类型。

Ø 

类是一种复杂的数据类型,它是将不同类型的数据和与这些数据相关的操作封装在一起的集合体。

在类体中不允许对所定义的数据成员进行初始化。

Ø  对象

类的实例

Ø  构造函数

构造函数是一种特殊的类成员函数,它的作用是对类的数据成员进行初始化和分配内存。

特点:

1、构造函数可以重载。

2、在程序中不能显示的调用构造函数,当创建对象时构造函数将自动被调用。

3、构造函数是成员函数,函数体可以写在类体内,也可以写在类体外。

4、构造函数是一个特殊的函数,函数名与类名相同,该函数不指定类型说明,它有隐含的返回值,该值由系统内部使用。

5、运算符new用于建立在生产期可控的对象,new返回指向所创建的对象的指针。new运算符与构造函数一同起作用,当用new运算符动态创建对象时,构造函数将被自动调用。

Ø  拷贝初始化构造函数

拷贝初始化构造函数是一种特殊的成员函数,其功能是用一个已知的对象来初始化一个被创建的同类的对象。

特点:

1、拷贝初始化构造函数名和类名相同,因为它也是一种构造函数。

2、拷贝初始化构造函数只有一个参数,并且是对某个对象的引用。

3、每个类都必须有一个拷贝初始化构造函数,如果类中没有说明拷贝初始化构造函数,则编译器将自动生成一个缺省的拷贝初始化构造函数,并作为该类的公有成员。

Ø  析构函数

析构函数也是一种特殊的类成员函数,它的作用是释放在构造函数中分配的内存空间。

特点:

1、在一个类中只能定义一个析构函数,且不能重载。

2、析构函数可以被显示的声明,也可以由系统自动调用。

3、析构函数是成员函数,函数体可以写在类体内,也可以写在类体外。

4、当一个对象是用new运算符动态创建时的,在使用delete运算符释放它时,delete将自动调用析构函数。

Ø  内联函数

C++语言之所以引入内联函数,主要是为了解决程序中函数调用的效率问题。

内联函数和宏的比较:

1、对内联函数的调用是由编译器进行处理的,而对宏的调用是由预处理进行扩展的

2、内联函数调用时,编译器要检查传递过来的参数类型,确保不传入非法类型

3、如果传入函数是表达式,则此表达式值仅仅一次

4、宏的优点是你传给宏什么数据,它就返回同一个类型

Ø  静态成员

静态成员的提出是为了解决数据共享的问题。

1、静态数据成员

静态数据成员的初始化需要注意以下几点:

l  静态数据成员的初始化在类体外进行,前面不加static,以免与一般的静态变量或对象混淆。

l  初始化时不加该成员的访问权限控制符。

l  初始化时使用作用域运算符来标明它所属类,所以它属于类的成员,不属于对象的成员。

2、静态成员函数

公有的静态成员函数的一个重要的作用就是实现访问类的私有静态数据成员。

定义静态成员函数时注意以下几点:

l  由于关键字static不是函数类型的一部分,所以在类定义之外定义静态成员函数时不能用static

l  静态成员函数不能被说明为虚函数

l  一个函数不能同时定义静态成员函数和非静态成员函数

Ø  友元函数和友元类

1、友元函数

使用友元函数的目的是为了提高程序的效率。友元函数可以直接访问对象的私有成员,因此节省了调用类的成员函数的时间开销。

友元函数的另一个优点是使程序员不必考虑好类的各种使用情况才能设计类,而是可以根据需要使用友元函数增加类的接口。

友元函数的缺点是,由于它可以访问私有成员,因而破坏的类的封装性和隐藏性,导致程序可维护性差。

因此,建议应当尽量不使用或少用友元函数。

   使用友元函数时注意以下几点:

l  在声明友元函数时,可以声明为公有的,也可以声明为私有的

l  类的友元函数不是本身的成员函数,因此它没有继承性

l  友元函数不能使用存储类修饰符来限定

2、友元类

友元类和友元函数类似。当一个类(类B)作为另一个类(类A)的友元时,这就意味着这个类(类B)的所有成员函数都是另一个类(类A)的友元函数。

Ø  对象指针

对象指针分为两类:

l  指向类类型对象的指针

l  指向类成员的指针

Ø  继承与派生

继承是一种客观世界中普遍存在的机制,它可以使后辈从前辈那里得到属性和行为特征,而继承的过程就叫做派生。

继承方式

基类中的访问权限

派生类中的访问权限

公有继承

Public

Protected

Private

Public

Protected

不可访问

私有继承

Public

Protected

Private

Private

Private

不可访问

保护继承

Public

Protected

Private

Protected

Protected

不可访问

1、公有继承方式

l  基类成员对其对象(基类对象)的可见性:公有成员可见,私有和保护成员不可见。

l  基类成员对派生类的可见性:公有成员和保护成员可见,而私有成员不可见。

l  基类成员对派生类对象的可见性:公有成员可见,私有和保护成员不可见。

2、私有继承方式

l  基类成员对其对象(基类对象)的可见性:公有成员可见,其他成员不可见。

l  基类成员对派生类的可见性:公有成员和保护成员是可见的,而私有成员是不可见的。

l  基类成员对派生类对象的可见性:所有成员都是不可见的。

3、保护继承方式

l  基类成员对其对象(基类对象)的可见性:公有成员可见,其他成员不可见。

l  基类成员对派生类的可见性:公有成员和保护成员是可见的,而私有成员是不可见的。

l  基类成员对派生类对象的可见性:所有成员都是不可见的。

4、继承情况

l  在公有继承的情况下,派生类的对象可以直接访问基类的共有成员

l  在私有继承的情况下,基类的公有和保护成员都将成为派生类的私有成员

l  在私有继承的情况下,基类的保护成员将成为派生类的私有成员,而无法再向下继承

l  基类的保护成员在派生类中仍然是保护成员

l  基类的保护成员在公有派生的情况下可以被继承到派生类的派生类

l  基类的保护成员对基类而言相当于私有成员,但可以由派生类访问

l  在保护继承的情况下,基类的公有成员和保护成员都成为派生类的保护成员

5、构造函数和析构函数的执行

派生类的构造函数和析构函数的执行是很重要的问题

当创建派生类对象时,首先要调用基类的构造函数,接下来调用派生类字节的构造函数;而当对象销毁时,析构函数的调用次序正好相反,首先调用派生类的析构函数,然后再调用基类的析构函数。

6、多继承的二义性

一般来说,在派生类中对基类成员的访问应该是唯一的。但是,由于多继承的情况下,可能造成对基类某个成员的访问出现不唯一的情况。这就是对基类成员访问的二义性。

l  通过作用域限定符

l  使用虚基类

虚基类的说明是用在定义派生类时,写在派生类名的后面。

Ø  函数和运算符重载

1、函数重载

函数重载是指同一个函数名可以对应着多个函数的实现。函数重载时要求函数的参数或者至少有一个类型不同,或者个数不同。而对于函数的返回值类型没有要求,可以相同,也可以不同。

l  重载与覆盖的区别

重载:相同的作用域,函数名相同,函数的参数不同,virtual关键字可有可无。

覆盖:不同的作用域,函数名相同,函数的参数相同,基类中的函数必须有virtual关键字。

l  隐藏

如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏。

    如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。此时,基类的函数被隐藏。

2、运算符重载

运算符重载是指同一个操作符可以实现不同的功能,它与函数重载的概念相似。

l  重载算术运算符

l  重载为类的友元函数

声明重载为类的友元函数目的指在访问类的私有数据成员。

 

²  C++语言中,几乎所有的运算符都可以重载,不允许重载的运算符是:.       ::     .*    ?

²  运算符重载不会改变原来运算符的优先级和结合性

²  运算符重载实际是一个函数,所以运算符重载实际上是函数的重载

²  运算符重载要坚持:不能改变运算符原有的优先级;不能改变运算符的操作个数;不能改变运算符原有的结合性;不能改变运算符原有的语法结构。

²  使用运算符时要遵守的原则:重载的运算符含义必须清楚;重载的运算符不能有二义性。

²  运算符重载一般采用成员函数形式和友元函数形式的两种方式。

Ø  Volatile修饰符

作用:告诉编译器无需对变量作任何的优化,即无需将它放到一个寄存器中,并且该值可被外部改变。对于多线程引用的全局变量来说,volatile是一个非常重要的修饰符。

Ø  _variant_t类型

_variant_tVARIANT的封装类,其赋值可以使用枪支类型转换,其构造函数会自动处理这些数据类型。使用时需加上#include <comdef.h>

_variant_t类型克服了普通数据类型在32位机器上的显示,普通数据类型在32位上只能显示10位,而_variant_t数据类型能显示100位。

Ø  回调函数

回调函数是应用程序提供给Windows系统DLL或其它DLL调用的函数,一般用于截获消息、获取系统消息或处理异步事件。应用程序把回调函数的地址指针告诉DLL,而DLL在适当的时候会调用该函数。

回调函数必须遵守事先规定好的参数格式和传递方式,否则DLL一调用它就会引起程序或系统崩溃。通常情况下,回调函数采用标准WindowsAPI的调用方式,即__stdcall,当然DLL编制者可以自己定义调用方式,但客户程序也必须遵守相同的规定。

__stdcall方式下,函数的参数按从右到左的顺序压入堆栈,除了明确指明是指针或应用外,参数都按值传递,函数返回之前自己负责把参数从堆栈中弹出。

Ø  虚函数与多态性

1、基类指针与派生类指针

为什么将派生类对象地址赋给基类指针是合法的?因为C++的继承采用了复制继承的方式,派生类的对象要为基类的所有成员分配内存空间(成员函数则分配函数指针空间),将它们存放在此空间,然后再存放派生类新增的成员;将基类对象的地址赋给派生指针需要强制类型转换,但它是不安全的,因为程序员很有可能使用这个指针来访问并没有实际定义的成员。

2、虚函数

声明虚函数时要使用关键字virtual。、

Virtual 类型 函数名(参数列表);

派生类中对基类的虚函数进行替换时,要求派生类中说明的虚函数和基类中的被替换的虚函数之间满足如下条件:

l  与基类的虚函数有相同的参数个数。

l  其参数的类型与基类的虚函数的对应参数类型相同。

l  其返回值或者与基类虚函数的相同,或者都返回指针或引用,并且派生类虚函数所返回的指针或引用的类型是基类中被替换的虚函数所返回的指针或引用的基类型的子类型。

l  虚函数的引入极大地方便了代码重用,它使得程序员避免了逐个详细定义每一个类。正是在引入虚函数的基础上,类的层次关系得以实现。

3、多态性
      多态性是指同一个接口名称具有不同的功能,也就是说当相同的消息被不同类型的对象接收时将导致完全不同的行为。
4、纯虚函数

纯虚函数是一种特殊的虚函数。

Virtual 类型 函数名(参数列表)= 0

5、抽象类

如果一个类包含有纯虚函数,则这个类称为抽象类。抽象类是一种特殊类,它是为了抽象和设计的目的而建立的,它处于类的继承层次的较上层。

抽象类的主要作用是将有关的类组织在一个继承层次结构中,由它来为它们提供一个公共的根,相关的子类都是从这个根派生出来的。

在定义抽象类的派生类时,必须提供基类纯虚函数的具体实现,或者仍然将纯虚函数说明为纯虚函数,否则编译器将给出错误信息。如果派生类给出了纯虚函数的集体实现,则此派生类是一个具体的类,可以创建此类的对象;如果派生类只是继承了基类的虚函数,则此派生类仍然是一个抽象类。

Ø  模板

1、函数模板

l  函数模板:相当于一个函数模子,可以用这个模子套印出许多功能相同、而参数类型和返回类型不同的函数。

l  声明:template <class X> void myswap(X &a, X &b)

l  模板函数与重载函数的区别。

模板函数和重载函数是非常类似的,都是一组名字相同的函数,模板函数处理的是只处理的数据类型不同,各个函数的内部行为是一样的;而重载函数除了处理的数据类型不同外,各个函数的内部行为时不一样的。

2、  类模板

l  类模板和模板函数的定义类似。

l  声明:template <class SType> class mystk

mystk类模板中的类型参数SType,它代表了栈中存储对象的类型。要用类模板生成对象,必须先要给类模板的参数指定具体的数据类型,即类模板的实例化,类模板名 <具体的数据类型>

mystk<int> istack

l  类模板的实例化与类实例化是两个不同的过程。类模板的实例化结果是生成实实在在的类;而类的实例化结果是生成对象,要为类对象分配空间,同时调用相应的构造函数初始化对象。

l  当在类模板体外定义模板的成员函数时,要在开头写上template<class SType>,后面是函数的说明,在函数名前要加上mystk<SType>::作用域说明符,表示此函数是mystk类模板的函数,SType是模板参数表中说明的参数。

3、类模板的派生问题

1、普通类作为基类

2、类模板作为基类

注意程序的书写格式。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多