编程语言----->设计模式---->架构设计(Object-Oriented Programming思想)
1、C++中有关类和对象的基本部分
(1)从C到C++
C++ | C |
语言风格更改加简洁 类型检查更严格 支持真正意义上的枚举类型 参数匹配更精确 禁止使用隐式声明 | 特点:接近底层的语言、小型语言 (标准库函数)、弱类型; 优点:高效、可移植性、灵活 缺点:更加容易隐藏错误,晦涩(不好理解) |
(2)名字空间 : namespace 名字空间名{ 名字空间成员; }
(3)C++的结构、联合和枚举
● C++的结构里面可以定义函数。
● C++里定义结构型变量的时候可以省略 struct 关键字 。
● C++中的声明联合类型的变量可以不加 union 关键字,支持匿名联合 。
● C++的枚举是一个独立的数据类型,而不是整数类型。
以上体现C++是一种强类型的语言。
(4)函数的重载、缺省参数、哑元、内联
● 函数重载:在同一个作用域中,函数名相同,参数表不同的函数之间构成重载关系。
重载解析原则:完全匹配>常量匹配>升级转换>标准转换>自定义转换>省略号转换
函数指针的类型决定其具体指向的重载版本,而不是由实参的类型决定。
● 如果为函数的一个参数指定了缺省值,那么该参数右边的所有参数都必须有缺省值。
当定义和声明分开的情况下,缺省参数只能用在函数的声明中,且注意防止与重载发生冲突。
● 哑元参数保证函数的向后兼容,也可以实现函数的重载(提高代码的可读性)。
● 内联函数以空间换取时间的方式保持了函数的特性,同时避免了函数调用的开销。
内联函数,在编译期,以二进制代码替换。
inline关键字仅仅表示希望该函数被编译为内联,究竟会不会成员内联由编译器决定。通常
情况下,大函数和递归函数不会被处理为内联。
--------------------------------------------
编译器:堆栈操作——内存检查、表达式计算等。
预编译器:宏替换(文本置换)。
--------------------------------------------
(5)引用(以下几点可以判别与指针的区别)
引用实际上是一个变量的别名。
● 引用必须初始化,且必须用变量初始化。只有const型引用才能引用常量,例如:
const int& rc=10; 不能对const引用做赋值。
● 不可能有空引用,必须确保引用和一块合法的存储单元关联。
● 当一个引用被初始化为指向一个对象,它就不能改变为指向另一个对象。
引用是用指针来实现的,且const和指针常应用于输出参数中。
(6)类型转换
● 静态类型转换: static_cast<类型>(变量) —— 编译期时检查
场合:需要编译器对类型转换安全性进行检查、将void*转换为具体类型的指针。在源类型
和目标类型之间只有有一个方向上可以做隐式类型转换,那么在两个方向上就都可以
做静态类型转换。
● 动态类型转换:dynamic_cast<类型>(变量) —— 编译期、运行时检查
场合:用于在具有多态特性的父子类之间的转换
● 常量类型转换:const_cast<类型>(变量)
场合:去除指针或者引用上的 const 属性
● 重解释类型转换:reinterpret_cast<类型>(变量) —— 编译期、运行时均不检查
场合:允许对任意类型的指针进行转换、在指针和整型之间进行转换
--------------------------------------------------------------------------------------------
C++之父给C程序员的建议:尽量少用宏,而用const/enum、inline和模板;少用malloc/free,代之用new/delete;少用 char* 字符串,代之以 string ;变量随用随声明;避
免使用void*、指针算数、联合和强制类型转换;OOP思想。过程/步骤->对象(行为和属性)( Object-oriented Programming )
(7)类里面的特性
● this指针
1、一般而言,关键字this是一个指针,对于一般成员函数,它指向调用该成员函数的对象,而对于构造函数,它则指向这个正在被构造的对象。
2、在构造函数中可以通过 this 指针区分成员变量和局部变量(包括参数) 。
3、基于this指针的自身引用还被用于支持多重串联调用的场合 。
4、将this 指针作为函数的参数,实现对象间的交互 。
● const成员函数和const对象
1、常量型成员函数中的this指针为常量型,以此防止对成员变量的意外修改。
union是什么类型2、被声明为 mutable 的成员变量可以在常量型成员函数中被修改 。
3、常量型成员函数和具有相同签名的非常量型成员函数构成重载关系。
4、当常量型成员函数与非常量型成员函数构成重载关系时,非常量对象会优先选择非常量
型成员函数。
5、常量型对象(包括指针和引用)只能调用其常量型成员函数。
● 对象的创建
栈 | 堆 | |
创建对象 | 类名 对象名(构造参数); //隐式构造 类名 对象名=类名(构造参数); //显式构造 | 类名* 对象指针= new 类名(构造参数); |
创建对象数组 | 类名 数组名[元素个数]= {类名(构造参数),...}; //元素个数可以缺省 | 类名* 对象(数组)指针= new 类名[元素个数]; |
● 构造函数
1、默认的无参构造函数
如果一个类中没有定义任何构造函数,系统就会自动提供一个无参构造函数。如果为一个类定义了构造函数,系统就不会在为该类提供任何构造函数。
构造函数可以重载,带参构造函数成员变量在内存中创建是在构造器中创建。
2、初始化列表
初始化的顺序依赖与成员变量定义的顺序
使用场合:
① 需要对类类型的成员变量做初始化;
② 含有引用或常量型成员
3、拷贝构造函数
◆ 拷贝构造:用一个已有的对象去构造另一个同类型的副本对象。
◆ 拷贝构造函数的实现
class 类名{
类名(const 类名& 源对象的引用){
从源对象到当前对象的复制;
}
};
◆ 拷贝构造发生的时机
① 构造对象副本
② 以对象作为函数的参数和返回值
③ 以对象的方式捕获异常
◆ 如果没有为一个类提供自定义的拷贝构造函数,系统就会提供一个缺省的拷贝构造函数,实现从源对象到目标对象的复制。
◆ 某些情况下系统提供的缺省拷贝构造函数可能无法实现满足具体的应用需求。这时就有必要提供自定义的拷贝构造函数(深拷贝)。
1 浅拷贝:由默认(缺省)的拷贝构造函数所实现的数据成员逐一赋值,两个
对象指向同一个内存空间。
2 深拷贝:必须显式地定义一个自定义的拷贝构造函数,使之不但赋值数据成
员,而且还为两个对象分配各自的内存空间。
4、拷贝赋值函数
◆ 拷贝赋值:用一个已有的对象赋值给另一个同类型的副本对象 。
对于一个已经初始化的对象进行赋值操作,如果原有的对象有内存分配的情况,则应先释放掉,而且还要检查这两个对象是否相等(避免自赋值)。
if(&array!=this){ If(m_data) { delete m_data ; m_data = NULL ; } }
◆ 拷贝赋值函数的实现
class 类名{
类名& operater=(const 类名& 源对象的引用){
从源对象到当前对象的复制;
}
};
&(引用)主要作用:为了联用表达式,例如:s1=s2=s3;
◆ 如果没有为一个类提供自定义的拷贝赋值函数,系统就会提供一个缺省的拷贝赋值函数,实现从源对象到目标对象的复制。(拷贝赋值函数同样存在浅拷贝和深拷贝问题)。
◆ 某些情况下系统提供的缺省拷贝赋值函数可能无法实现满足具体的应用需求,这时就有
必要提供自定义的拷贝赋值函数。
5、拷贝构造函数与拷贝赋值函数的区别以及自定义拷贝构造和赋值函数自定义的时期
◆ 区别:
拷贝构造函数:在创建对象的同时完成赋值。
拷贝赋值函数:对象已经存在,后赋值。
◆ 拷贝构造函数与拷贝赋值函数自定义的时期:
默认的拷贝函数,不但不能提供深拷贝,还可能产生内存泄漏。因此,当程序
中有new、指针成员、复合对象的时候,需要实现自定义的拷贝构造函数和拷贝赋
值函数。
● 析构函数
1、没有参数,析构函数不能重载。
2、缺省析构函数
① 对于未定义析构函数的类,系统会提供缺省析构函数,该析构函数负责销毁该类的成
员变量;
② 缺省析构函数不负责释放动态分配的资源。
3、对于动态分配的资源,必须通过自己定义的析构函数进行释放。
4、析构函数是释放的资源不仅限于内存资源
● 静态成员
1、静态成员属于类的,唯一的,可为该类对象所共享。
2、静态成员函数只能访问静态成员。
3、非静态成员函数既能访问静态成员,也能访问非静态成员。
4、静态成员变量必须在类的外部定义并初始化
5、既可以通过类也可以通过对象访问静态成员,但最好通过类。
6、静态成员同样受类的访问控制属性的影响。
7、静态成员函数不能接受this指针,只能访问静态成员变量。
● 成员指针 (相对地址)
1、指向成员变量的指针
1)定义语法: 成员变量类型 类名::*指针变量名;
string Student::*pstrName;
pstrName是一个指向Student类中string类型的成员变量的指针。
2)赋值即初始化语法: 指针变量名=&类名::成员变量名;
pstrName=&student::m_strName;
pstrName指向Student类的m_strName成员变量
3)解引用语法: 对象.*指针变量名、对象指针->*指针变量名(.*和->*分别是一个整体)
2、指向成员函数的指针
1)定义语法:成员函数返回类型(类名::*指针变量名)(形参表);
void(Student::*pfuncSetName)(const string&);
2)赋值和初始化语法: 指针变量名=&类名::成员函数名;
pfuncSetName=&Student::SetName;
3)解引用语法: (对象.*指针变量名)(...)、(对象指针->*指针变量名)(....)
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论