(3.2)狄泰软件学院C++课程学习剖析三
对课程前面40课的详细回顾分析(一)
0、
- int main()
- {
- // ① Array t(3,3); //普通模式
- // ② Array *t=new Array(3,3); //指针方式
- // cout<<t->a<<endl;
- //③ Array t=Array(3,3); //临时对象
- //cout<<t.a<<endl;
- int b=3;
- int *p=&b;
- int *a=new int(b); //在堆空间申请一个int 里面存的值为b
- cout<<p<<endl<<a<<endl;
- return 0;
- }
1、在最初语言规划的阶段,C语言的出现纯粹是为了编写unix操作系统;造成了C语言没有太多深思熟虑的过程,遗留了太多低级语言的特征; 进而造成了软件的可维护性和可重用性差。
c++中的register关键字对于C语言只是一个兼容性问题,在c++中遇到register关键字的时候会自动忽略掉;在c++中的任意标识符都必须显式的指明类型 。
2、
C语言中的const修饰的变量(无论是全局变量还是局部变量都只是只读的,本质上还是变量,不是真正意义上的常量;只在编译期间有用,在运行时无用,所以我们可以骗过编译器对一个const修饰的变量进行修改)
骗过编译器修改const修饰变量的的方法:
- int main()
- {
- const int a=5;
- int *p=(int *)&a;
- *p=4;
- printf("a=%d\n *p=%d\n",a,*p);
- return 0;
- }
但是在c++中能够定义真正意义上的常量,是不能够修改的。
extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。此外extern也可用来进行链接指定。
- int main()
- {
- int a=5;
- int *p1=&a;
- int &b=a; //引用
- b=4;
- int *p2=&b;
- printf("a=%d\n",a);
- printf("%p\n%p\n",*p1,*p2);
- return 0;
- }
int * p
(1)const int *p
(2)int const *p
(3)int * const p
(4)const int *const p
引用和指针的区别和联系:
★ 相同点:
1. 都是地址的概念;
指针指向一块内存,它的内容是所指内存的地址;引用是某块内存的别名。
★ 区别:
1. 指针是一个实体,而引用仅是个别名;
2. 引用使用时无需解引用(*),指针需要解引用;
3. 引用只能在定义时被初始化一次,之后不可变;指针可变;
引用“从一而终” ^_^
4. 引用没有 const,指针有 const,const 的指针不可变;
5. 引用不能为空,指针可以为空;
6. “sizeof 引用”得到的是所指向的变量(对象)的大小,而“sizeof 指针”得到的是指针本身(所指向的变量或对象的地址)的大小;
typeid(T) == typeid(T&) 恒为真,sizeof(T) == sizeof(T&) 恒为真,
但是当引用作为成员时,其占用空间与指针相同(没找到标准的规定)。
7. 指针和引用的自增(++)运算意义不一样;
3、c++中可以使用const常量代替宏常数定义;同样我们可以使用内联函数来替代宏代码片段。内联函数在声明时inline关键字必须和函数定义结合在一起,否则编译器会直接忽略内联请求。c++编译器可以将一个函数内联编译,所谓的内联编译就是编译器直接将函数体插入到函数调用的地方,类似于宏定义替换;内联函数省去了普通函数调用时的额外开销(压栈、跳转、返回);但是inline只是一种请求,c++编译器对于函数的内联请求不一定都会满足。
4、c++可以在函数声明时为参数提供一个默认值,当函数调用时没有提供参数时候则使用默认值;尤其需要指出的一点是参数的默认值必须在函数声明中指定;当函数声明和函数定义中都有一个默认值时候则选用函数声明中的默认值,同时可以在函数参数中使用占位参数,占位参数只有函数参数类型声明,而没有参数名。
5、c++中int function()和int function(void)没有区别,都表示无参数接收,返回值为int的函数;但是在C语言中前者表示可以接收任意参数,后者才表示不接受参数。
6、重载函数本质上是一个个相互独立的不同的函数,函数重载是由函数名和参数列表决定的,返回值不能作为判断依据。
extern关键字可以实现C语言和c++的相互调用。函数重载在c++中才可以,在C语言中不行。
7、new关键字
8、
const引用其实就是const int * const p,生成一个新的只读变量。
const int &a=b;也是一个只读变量
volatile const int &a;也是一个只读变量
const int &a=5;//常量
9、c++中的强制类型转换
(1)dynamic_cast操作符:用于基类和派生类之间的类指针或者类引用的转换,基类中必须要有虚函数。
用法:
classB
{
public
:
int
m_iNum;
virtual
void
foo();
};
classD:publicB
{
public
:
char
* m_szName[100];
};
void
func(B* pb)
{
D* pd1=
static_cast
<D*>(pb);
D* pd2=
dynamic_cast
<D*>(pb);
}
交叉转换
classA
{
public
:
intm_iNum;
virtual
void
f(){}
};
class
B:
public
A
{
};
class
D:
public
A
{
};
void
foo()
{
B*pb=newB;
pb->m_iNum=100;
//D*pd1=static_cast<D*>(pb);//compile error
D*pd2=
dynamic_cast
<D*>(pb);
//pd2isNULL
delete
pb;
}
(2)const_cast操作符:用于去除变量的const只读属性,强制转换的目标类型必须是指针或者引用。
- int main()
- {
- const int a=3;
- int *p=const_cast<int *>(&a);
- *p=5;
- cout<<*p<<endl; //*p=5
- return 0;
- }
(3)static_cast操作符:可以把它完全当作C语言中的暴力强制类型转换,该操作符用于非多态类型的转换,任何标准转换都可以使用,即static_cast可以把int转换为double,但不能把两个不相关的类对象进行转换,比如类A不能转换为一个不相关的类B类型,但是 对于两个相关的类转换其类对象是可以的。static_cast本质上是传统c语言强制转换的替代品。
(4)reinterpret_cast操作符:用于指针类型间的类型转换 ,用于整数和指针之间的类型转换。
代码示例:
- int main()
- {
- int a=3;
- int *p=&a;
- cout<<p<<endl;
- double b=3.90;
- double *p1=&b;
- cout<<p1<<endl;
- p1=reinterpret_cast<double *>(p);
- // p1=(double *)p; //c语言的转换方法
- cout<<p1<<endl;
- return 0;
- }
10、深究引用(引用和指针的关系深究)
对于引用变量的内部实现,可以得出如下结论:
引用变量:
1)引用的内部实现为相当于一个指针常量 int *const p ,与指针的实现方式类似;
2)引用变量内存单元保存的指向变量地址(初始化时赋值),与指针不同地方时,引用变量在定义时必须初始化,而且使用过程中,引用变量保存的内存单元地址值是不能改变的(这一点通过编译器来实现保证);
3)引用也可以进行取地址操作,但是取地址操作返回的不是引用变量所在的内存单元地址,而是被引用变量本身所在的内存单元地址;(对引用变量的取地址操作相当于取内容操作,如果要想取得引用变量的地址,应使用两次取地址符号,如:&(&a) )
4)引用的使用,在源代码级相当于普通的变量一样使用,但在函数参数传递引用变量时,内部传递的实际是变量的地址值(这种机制的实现是通过编译器(编译手段)来实现的)。
不能将引用简单理解为变量的代记符号,引用本身是通过指针实现,并且占用相应的内存空间。
参考博客:http://blog.csdn.net/thisispan/article/details/7456169
11、重载、重写和多态的区别?
c++中的多态性本质上是为了接口重用,体现在函数重写上;而函数重载只发生在一个类中,不像重写那样在基类和子类中,所以不算是多态性的体现。
重定义和重写虽然都发生在基类和派生类之间,但是重写是对基类的虚函数进行重写(函数名,参数列表都需要跟基类的一致),而重定义是对基类的非虚成员函数进行函数定义,
函数 的参数列表不用跟基类的保持一致。
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
12、类之间的基本关系:组合和继承。组合是has-a,整体和局部的关系;继承是is-a的关系,子类拥有父类的全部属性和方法。
13、一个类中可以存在多个重载的构造函数,构造函数的重载依靠C++的重载规则。
14、
15、析构函数和构造函数的一些问题:
注意一点:析构函数是在类对象释放时候才被调用的,对于其他的指针可以用delete删除。
析构函数(destructor) 与构造函数相反,当对象结束其生命周期时(例如对象所在的函数已调用完毕),系统自动执行析构函数。析构函数往往用来做“清理善后” 的工作(例如在建立对象时用new开辟了一片内存空间,delete会自动调用析构函数后释放内存)。
以C++语言为例:[1] 析构函数名也应与类名相同,只是在函数名前面加一个位取反符~,例如~stud( ),以区别于构造函数。它不能带任何参数,也没有返回值(包括void类型)。只能有一个析构函数,不能重载。如果用户没有编写析构函数,编译系统会自动生成一个缺省的析构函数(即使自定义了析构函数,编译器也总是会为我们合成一个析构函数,并且如果自定义了析构函数,编译器在执行时会先调用自定义的析构函数再调用合成的析构函数),它也不进行任何操作。所以许多简单的类中没有用显示的析构函数。
C++语言析构函数格式
1
2
3
4
5
6
7
8
9
|
class <类名> { public : ~<类名>(); }; <类名>::~<类名>() { //函数体 }; |
1
2
3
4
5
6
7
8
9
|
class T { public : ~T(); }; T::~T() { //函数体 }; |
(3.2)狄泰软件学院C++课程学习剖析三的更多相关文章
- (3.3)狄泰软件学院C++课程学习剖析四
对课程前面40课的详细回顾分析(二) 1.一个类的成员变量是对于每个对象专有的,但是成员函数是共享的. 2.构造函数只是决定一个对象的初始化状态,而不能决定对象的诞生.二阶构造人为的将初始化过程分为了 ...
- (3.1)狄泰软件学院C++课程学习剖析二
深度剖析C++第二部分 1.通过对象名能够访问public成员变量.每个对象的成员变量都是专属的,成员变量不能够在对象之间共享. 2.需求:统计在程序运行期间某个类的对象数目,保证程序的安全性(不能使 ...
- (3)狄泰软件学院C++课程学习剖析一
深度剖析C++第一部分 1.类是一种模型,这种模型可以创建出一个对应的实体.有了类不一定有对应的实体,但是一个实体必定属于某一个类. 2.类用于抽象的描述 一类事物所持有的属性和行为:对象是具体的事物 ...
- Linux网络课程学习第三天
第三天在线视频学习. 学习内容:继续详细介绍了第二章节 Linux常用命令的使用方法. 学习感受:万事开头难,作为Linux零基础的我相信在这本书学完之后会有所收获. 学习心得:记住刘老师的一句口头禅 ...
- Excel课程学习第三课排序与替换
一.排序 1.简单排序 点到某一个单元格,然后选择排序,就可以按照相应的顺序来排序. 2.自定义排序 按照重要性条件来排序 也可以按照重要性从轻到重挨个排序. 3.按颜色排序 4. 按照中文数字排序, ...
- Linux课程学习 第三课
生活中的许多事,并不是我们不能做到,而是我们不相信能够做到 https://www.linuxcool.com/ 一个很实用的Linux命令查询网站,并且还有发音 如果我们在系统终端中执行一个命令后想 ...
- SpringBoot课程学习(三)
一.YAML格式的基本语法 (1)格式: 大小写敏感 数据值前边必须有空格,作为分隔符 使用缩进表示层级关系 缩进时不允许使用Tab键,只允许使用空格(各个系统 Tab对应的 空格数目可能不同,导致层 ...
- 王之泰《面向对象程序设计(java)》课程学习总结
第一部分:理论知识学习部分 总复习纲要 1. Java语言特点与开发环境配置(第1章.第2章) 2. Java基本程序结构(第3章) 3. Java面向对象程序结构(第4章.第5章.第6章) 4. 类 ...
- C语言课程学习的总结
C语言课程学习的总结 学习C程序这门课一年了,这是我们学的第一门专业课.在大学里,C语言不但是计算机专业的必修课程而且也是非计算机专业学习计算机基础的一门必修课程.所以作为我这个计算机专业的学生来说当 ...
随机推荐
- django 的多对多关系
django里自带的多对多表创建 其实就是两个多对一关系各自关联,在第三张表上 多对多的增加 add()可以传数值 例如 add(1)或数组 add(*[2,3]) 多对多反向操作 自己创建第三张表, ...
- PL/SQL基本操作
1.常规过程化形式 declare o_booking_flag ); begin -- Call the procedure destine_ticket(', , 'E', , o_booking ...
- 洛谷 P2196 挖地雷 & [NOIP1996提高组](搜索,记录路径)
传送门 解题思路 就是暴力!!! 没什么好说的,总之,就是枚举每一个起点,然后暴力算一遍以这个点为起点的所有路径,在算的过程中,只要比目前找到的答案更优,就有可能是最后的答案,于是就把路径更新一遍,保 ...
- __init__ 和__new__的区别?
init 在对象创建后,对对象进行初始化. new 是在对象创建之前创建一个对象,并将该对象返回给 init.
- Find The Multiple (水题)
Given a positive integer n, write a program to find out a nonzero multiple m of n whose decimal repr ...
- Aniamtion加载动画
css新增样式Animation的运用 希望可以通过这个案例加深对Animation以及Transform 两大api的认识 效果图如下: 在这里需要注意的是:理应通过发送服务器请求来获取图片,从而达 ...
- 如何学习ios(摘自知乎https://www.zhihu.com/question/20016551)
著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处.作者:Wang Hailong链接:https://www.zhihu.com/question/20016551/answer/1 ...
- loadkeys - 调入键盘翻译表
总览 (SYNOPSIS) loadkeys [ -d --default ] [ -h --help ] [ -q --quiet ] [ -v --verbose [ -v --verbose ] ...
- newgrp - 登录到新的用户组中
总览 (SYNOPSIS) newgrp [ group ] 描述 (DESCRIPTION) Newgrp 改变 调用者 的 用户组标识, 类似于 login(1). 调用者 仍旧 登录 在 系统 ...
- fpga延时程序编写
//工匠小建 延时计数 100微妙计数 50M*0.00001-1 (个人理解:1s中50M次动作.那么100us多少次动作.做完这些动作就是延时)parameter delay_100us=16'd ...