C++知识点随笔(二):继承、多态

一、继承

继承是类之间的,对象之间没有什么关系,比如子类继承了父类的成员属性,并且子类的对象修改了这个成员属性,可是修改之后我们再去输出父类的成员属性发现并没有发生改变,原因是这两个对象本来就是两块空间里的,没有什么联系。 继承只是继承父类的成员属性,成员函数并不会发生继承,因为本来就只有一份儿,只不过子类可以使用父类的成员函数罢了。 我们用C语言的结构体来模拟一下C++的继承,其实就相当于在子结构体中定义了一个父结构体而已:

struct AA{int a;};struct BB{AA a;int b;};

如果子类拥有和父类同名的成员属性,可以通过类的作用域来区分:

<< endl;<< endl;

1. 继承的构造、析构函数: 继承的子类属性里面默认有一个父类的构造函数,并且放在首位,所以在执行子类的构造函数的时候,先执行初始化列表,而初始化列表的执行顺序是根据定义的顺序,由于父类的构造函数在子类定义成员属性的首位,所以先执行父类的构造函数,所以就会发生:先执行父类构造函数,再执行子类构造函数。析构的时候:先执行子类析构函数,后执行父类析构函数。 注意:子类的构造函数默认调用的是父类的无参的构造函数,如果父类的构造函数是有参数的,我们也可以手动在子类构造函数的初始化列表中定义(初始化列表的作用就是可以给当前类中new出的对象的构造函数传参数,上一篇中有介绍)。

2. 继承的方式: public继承:父类的访问修饰符到子类没有变 protected继承:把public变成保护 private继承:把public、protected 变成 private 注意: private成员继承了,但是不能直接用,想用就通过父类公共的函数;除了private成员其他的成员属性在子类中都可以用,但出了子类就要怎么继承的。只有公共的成员属性才可以在子类外使用,私有的和保护的在子类外都不能使用。私有继承的成员函数在子类外也不能使用。 总结: 无论哪种继承方式,都是改变父类的成员属性或成员函数在子类中的状态,并不会改变子类本身的成员,而我们在子类外使用子类和父类的成员的时候,只需要看他当前是什么状态,只有是public的才能在外部使用,其余的都不可以。

3. 父类指针指向子类对象:

CFather* pp = new CSon;

这样做的目的是为了:这样就可以使父类使用子类的成员了,通过多态来实现。需要注意的是,父类指针即使指向了子类的对象,可是父类指针也只是能用自己的成员而已,因为子类对象的空间里,前面的部分是父类的继承,后面的部分才是子类本身,当我们用父类的指针指向子类的对象的时候,只能使用子类前面继承父类的那部分空间,然而我们就是通过这部分空间,结合多态来实现父类使用子类成员的目的。 注意的是:构造函数调用的顺序和正常new子类对象一样,先执行父类的构造函数,再执行子类的构造函数。 我们在delelte这个指针的时候:

delete pp; //把 pp 指向的对象全部删除,就是 new 出的部分全部删除,但是调用析构看当前这个pp的类型

由于pp无法使用子类的空间,所以只会调用父类的析构函数,但是子类的成员(除了new的成员外)也会delete掉了,因为父类的析构函数里面会调用delete,而这个delete不会只销毁父类的留下子类的,而是将他们全部销毁。可是子类中new的成员属性一定是在子类的析构函数中delete的,所以因为我们没有调用子类的析构函数,所以这部分成员属性并不会被销毁,从而造成内存泄露。 所以我们如果不想造成内存泄露,就应该:

delete (CSon*)pp; //这样调用了子类的析构函数之后还会继续调用父类的析构,从而销毁了全部内容

注意:强转的作用是,把这个指针当做(CSon*)用一下,,用过之后pp还是原来的没有变。 虽然父类指针可以指向子类的对象,但是子类的指针不能指向父类的对象。不能用大的指针去指向一块儿小的地址,编译无法通过。

4. 重写、重载、隐藏: (1) 重写 子类重写父类的函数,函数名和参数必须相同,返回值可以不同,但是仅限于返回类型为父类或子类的指针这种类型的不同,如果返回int和char这种不同是不可以的。重写之后的函数可以通过加作用域的方式来调用。重写的函数必须是虚函数。 (2) 重载 相同的函数名,不同的参数,根据传参不同调用不同的函数。 (3) 隐藏 (或纵向重载) 把重载的两个函数分别放入父类和子类中,这样在调用的时候就不能通过参数的不同来调用了,而是通过作用域的不同来使用。

二、多态

多态的作用就是提高代码的扩展性,其实我们在C语言中也有提高代码扩展性的应用,比如:函数指针,我们只需要把函数的地址传进去就可以调用相应的功能,而不用把某个函数写死了。 多态实现代码如下:

#include <iostream>using namespace std;class CWater{public:()//virtual虚函数是实现多态的方法{cout << “CWater::Show”<< endl;}};class CMilk : public CWater{public:void Show(){cout << “CMilk::Show”<< endl;}};class CCoffee : public CWater{public:void Show(){cout << “CCoffee::Show”<< endl;}};class CBeer : public CWater{public:void Show(){cout << “CBeer::Show”<< endl;}};void Bottle(CWater* water) //无论传进来什么对象,都用父类的指针调用虚函数就可以实现{water->Show();}int main(){CMilk* milk = new CMilk;Bottle(milk);CCoffee* coffee = new CCoffee;Bottle(coffee);CBeer* beer = new CBeer;Bottle(beer);CWater* water = new CMilk;Bottle(water);system(“pause”);return 0;}

输出结果:

注意:父类本身的对象在使用虚函数的时候也会正常执行。

不曾见谁。则见朵花儿闪下来,好一惊。

C++知识点随笔(二):继承、多态

相关文章:

你感兴趣的文章:

标签云: