VC++学习笔记第二章

1、C++中的类,都是靠构造函数来创建对象的,虽然有的时候我们没有看见有显示的构造函数,但是实际上编译器会为我们定义一个没有任何参数的构造函数。但是只负责创建对象,不负责初始化,当然我们也可以通过自己定义一个这样的没有参数的构造函数,进行函数的重载。

如果我自己先定义了一个带参数的构造函数,但是之后我还是想用一个不带参数的,比如默认的情况下,这样,如果我还是想实现初始化的作用,那么就要自己重新定义不带参数的构造函数。因为编译器会观察,只要你定义了一个构造函数,无论是什么形式的,编译器都不会再给你提供任何参数。


2、有构造函数就有析构函数,构造函数是创建对象的,那么析构函数就是删除对象,清理内存的。尽管这两个函数可以不写任何东西,但是他们的内部清理,创建工作都由系统调用它们完成。并且,析构函数是不能够有参数存在的,每一个类只有一个析构函数。这和构造函数是不同的。


3、C++中,当我们用类每创建一个对象的时候,都随之产生一个this指针,这个指针指向我们创建的这个对象。不同的对象执行同一个函数,但是不同的对象产生的数据肯定都是不同的,那么调用的函数一样,怎么样区分每一个对象的不同的数据呢,就是用了this指针。


4、在类的继承中 ,基类的成员可以分为三类,公开的,私有的,被保护的,如果是子类是public继承的父类,那么对于这个子类的对象来说,只可以访问 父类中的public里面的成员,父类中的protected成员只能在子类中被访问,不能够再子类的外部访问,也就是说我可以在子类中定义一个方法,把父类中protected的方法添加进来,这样我可以通过子类对象访问它自己的方法间接访问到父类中的那个protected的方法,但是直接访问是不行的。而私有的方法和成员变量,只能在定义他的类里面进行访问,即使是在子类中也不能访问,无论是什么继承形式。


关于类的继承以及继承之后子类的访问权限,如下图所示:




5、再有类的继承发生的时候,程序默认先执行父类的构造函数,再执行子类的构造函数。而在执行析构函数的时候,先执行子类的析构函数,再执行父类的析构函数。



6、一般来说,当我们想创建一个子类对象的时候,都会自动调用父类的默认的不带参数的构造函数,但是如果我们在实现父类的时候仅仅写了一个带参数的构造函数的话,由于已经有了构造函数,编译器将不会为我们的父类创建默认的不带参数的构造函数。这样的话就可能会出错。还有一种原因就是,我们本意就是想在创建子类对象的时候执行父类带参数的构造函数,这样,我们就需要显式的调用父类的带参数的构造函数。

形式如下:
例如fish为子类,animal为父类

则在fish类的构造函数的后面:fish():animal(1,2){}

这样就算是显式的调用了父类带参数的构造函数,一方面避免出错,另一方面也比较人性化,可以传递自己想要的数值。

另外,如果类中的数据成员有常量要初始化的话,也可以在fish()后面利用逗号隔开进行初始化操作。

比如有一个常量const int a;

fish():animal(1,2), a(1){}即可


7、函数的覆盖

函数有重载和覆盖两种情况,函数的重载是发生在一个类里面,同名函数有着不同的特征标,根据不同的参数完成相同的操作。函数的覆盖是发生在父类和子类之间的,如果父类和子类中都有着同名的函数的话,那么子类的对象调用这个方法将会执行子类中的版本,屏蔽掉父类的版本,所以叫做函数的覆盖。这种功能可以让我们丢弃父类中不需要的特性,在子类中写自己想要的特性,增大了程序的灵活性。

但是如果我们特意想在执行自己特性的时候也执行父类的同名方法,可以在子类的方法中用作用域标识符进行调用父类中的方法。


8、当我们创建一个子类对象的时候,我们会首先调用父类的构造函数创建一个父类的对象,这时候创建的父类对象和子类对象在内存中是相邻的,子类对象的首地址也就是父类对象的首地址。所以在将子类对象的地址强制类型转换为父类对象地址的时候,不会出现数据丢失的情况,因为子类对象的地址就是父类对象的地址。


9、虚函数

虚函数,其实是C++中多态性的一个体现。如果我先定义了一个父类的指针p,把子类对象的地址pn传递给给他。父类和子类中均有一个同名的breath函数,那么此时p->breath()调用的是父类中的那个版本的函数。其实我们的本意是传递是哪个对象的值就应该调用哪个对象的方法。普通的成员函数,因为我们把子类的对象地址传递给父类对象的指针的时候,会发生强制类型转换,在程序运行之前,breath方法可能就已经绑定为父类中的方法了,如果此时我声明父类中的breath函数为虚函数的话,那么此时我们传递的是什么对象类型的地址,他就会调用这个对象所在类的函数。


总的来说,如果父类中被声明为是虚函数,那么在调用的时候就根据迟绑定的原则,根据调用对象的类型来调用相应的方法,如果此时子类中没有相应的同名函数,那么就只能调用父类中的方法,一旦子类中有此同名方法,那么肯定会调用子类中的。


10、纯虚函数

纯虚函数就是在虚函数的声明部分后面加上=0;例如

virtual void breath() = 0;

这样就声明了一个纯虚函数。这里还要介绍的一个概念就是,如果有一个没有被实现的纯虚函数所在的类,那么这个类应该叫做抽象类。如果父类红有纯虚函数,子类继承自父类,那么父类和子类都是抽象类。

为什么会存在纯虚函数,就是因为在基类创建的时候,有些功能明知道可能会变化很大,不好实现,但是这个功能呢又必须存在,所以只声明不定义。因为基类其实是为子类服务的,所以,不同的子类当对这个功能有不同的要求的时候,可以重新实现这个在基类中被声明的纯虚函数。


11、引用

一个 变量的引用就相当于一个变量的别名,当我们在定义一个引用的时候,我们必须在初始化的时候为这个引用指定一个相应的变量,也就说,在创建的时候就要确定这个引用是哪个变量的别名。

例如:
int a = 6;

int &b = a;

b = 5;

上面的三行代码,前两行是定义一个变量并且把一个引用初始化,第三行,b=5;你可能会以为这是把b当作了5的引用,其实是错的。一方面,引用只是对变量而言的概念,5算是一个常量,另外一方面,引用在初始化之后就不能再改变它绑定的那个变量的对象了。从引用初始化的哪一行代码以后,b这个引用变量和a变量的使用方法没有任何区别, 也就是说,对b的操作就是对a的操作。


12、引用和指针的区别

一般来说,引用和指针有着相同的作用,他们都可以更改他们指向的内存空间里面的数据, 两者的第一点区别就在于,引用是不需要占用内存空间的,但是一个指针是必须要占用一段内存空间来存储它所指向变量的地址值的,也就是说,引用和指针同时指向一个变量的话,那么引用是没有额外的内存需求的,但是指针是必须要的


变量的引用在函数传参的时候,会有更多运用。


13、在多继承中,基类的说明顺序会直接影响到,在创建子类对象的时候,执行父类构造函数的顺序。


14、抽象类是不能实例化对象的。


15、函数一般有重载,覆盖,隐藏三种形式

其中重载是发生在一个类里面的,其余两个都是发生在多个类之间的。

覆盖是发生在子类和基类之间的,子类和基类之间必须有着函数名和参数列表都相同的两个函数,并且基类中的这个函数被声明为虚函数。不属于这种情况的,就是隐藏。

16、引用和指针的两个区别

首先,指针是需要内存空间的,引用不需要

其次,普通指针是可以改变它内存当中的数据,从而指向其他位置的,而引用一旦被一个对象或者其他的变量赋值,那么就不能再改变它指向别的地方了。


17、一个C++程序的生成过程

首先,程序将处理带有#的预编译指令,由预处理器处理,之后编译源代码文件形成带有机器指令的obj文件,最后,通过连接操作,加入我们要引用得一些库函数,生成一个exe可执行文件。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值