继承和多态

一继承和多态

1总结:类和对象:体现了OOP封装和隐藏的思想

2.继承:体现了OPP的代码的复用和重用

3.组合:一个类定义对象是另一个类的成员对象 a part of ....

4继承:一个类的定义:[ 访问限定符] 已定义的过的类  a kind of ....

二.派生类继承什么东西

1.派生类继承了和基类除了构造函数和析构函数外的所有成员

基类的名字和派生类的名字相同是因为派生类还继承了类的作用域

2派生类中继承的基类成员的访问限定

继承方式                   基类的访问限定              派生类访问限定                        外部访问限定

                                    public                               public                                            可以

公有继承                     private                            不可见  可继承                             不可以

                                     protected                       protected                                       不可以

                                    public                               protected                                     不  可以

保护有继承                private                            不可见  可继承                             不可以

                                     protected                       protected                                       不可以

                                    public                               privite                                            不 可以

公有继承                     private                            不可见  可继承                             不可以

                                     protected                         privite                                           不可以t


3.private  和protecde    有什么区别

基类的privite的成员在派生类中不可见 不可访问,且外部也不能访问

基类的protected的成员在派生类中可访问,且外部也不能访问

4.不加继承方式的继承是什么方式

class此时默认的是私有继承

structt默认的为公有继承

三  派生类的构造过程

1先构造基类的部分,在构造派生类的,出作用域,先析构派生类,在析构基类

2在派生类的构造函数的初始化列表当中,指定基类部分的构造函数,不指名的话,基类就要调用默认的构造

例子:如果派生类没有定义构造函数,就调用基类的构造函数

class Base
{
public:
Base(int data) :ma(data) { cout << "Base()" << endl; }
~Base() { cout << "~Base()" << endl; }
void show() { cout << "Base::show()" << endl; }
void show(int val) { cout << "Base::show(int)" << endl; }
protected:
int ma;
};


class Derive : public Base
{
public:
//“Base”: 没有合适的默认构造函数可用
Derive(int data = 20) :mb(data), Base(data)//注意这里不能写ma(data)
{
cout << "Derive()" << endl;
}
~Derive() { cout << "~Derive()" << endl; }
/*void show()
{
cout << "Derive::show()" << endl;
//this->Base::show(); //派生类的同名方法中调用基类的同名方法
}*/
private:
int mb;
};
int main()
{
Derive d1;
d1.show();  // Base::
//d1.Base::show();
d1.show(10);//“Derive::show”: 函数不接受 1 个参数


return 0;
}

结果

Base()

Derive()

Base::show()

Base::show(int)

~Derive

~Base()



3基类和派生类同名方法之间的关系

(1)重载;

函数名相同,参数列表不同

作用域相同

(2)隐藏

隐藏必须出现在继承结构中

派生类和基类的方法名字相同,此时派生类只调用派生类的方法

class Base
{
public:
Base(int data) :ma(data) { cout << "Base()" << endl; }
~Base() { cout << "~Base()" << endl; }
void show() { cout << "Base::show()" << endl; }
void show(int val) { cout << "Base::show(int)" << endl; }
protected:
int ma;
};


class Derive : public Base
{
public:
//“Base”: 没有合适的默认构造函数可用
Derive(int data = 20) :mb(data), Base(data)//注意这里不能写ma(data)
{
cout << "Derive()" << endl;
}
~Derive() { cout << "~Derive()" << endl; }
void show()
{
cout << "Derive::show()" << endl;
//this->Base::show(); //派生类的同名方法中调用基类的同名方法
}
private:
int mb;
};
int main()
{
Derive d1;
d1.show();  // Base::
//d1.Base::show();
//d1.show(10);//“Derive::show”: 函数不接受 1 个参数


return 0;
}

结果:

Base()

Derive()

Derive::show()

~Derive

~Base()


、、、、、、、、、、、、、、、、

如果定义d1.show(10);//“Derive::show”: 函数不接受 1 个参数
会发生错误因为在派生类没有一个只带一个int参数的构造函数,

(3)重写、覆盖

在继承结构中,基类的方法和派生类的方法返回值,函数名,成员列表都相同,而且基类的函数是虚函数,那么派生类的函数也叫作虚函数,那么派生类的虚函数也叫重写、覆盖,

4.继承结构中,从上到下 从下到上的转换关系

(1)基类对象赋值给子类对象            不可以

(2)子类对象赋值给基类对象             可以

总结.只能从下向上转换

(3)基类指针指向子类对象                 可以

(4)子类指针指向基类对象               不 可以

5.虚函数

基类成员方法的返回值前加了vitual 关键字

在继承结构中,基类的方法和派生类的方法返回值,函数名,成员列表都相同,而且基类的函数是虚函数,那么派生类的函数也叫作虚函数,那么派生类的虚函数也叫重写、覆盖,

虚函数表:


6. 静态函数的绑定和动态组合

静态绑定:指定在编译时期的绑定,函数调用在编译时期就确定了;

动态绑定:在运行时期的绑定,通过寻找虚函数指针,找到虚函数表  再找到虚函数地址,进行调用,这都是发生在运行阶段

隐藏到底隐藏什么?覆盖就覆盖什么?

隐藏就是派生类的作用域把基类的作用域给隐藏了表中,

覆盖是在派生类的虚函数用派生类重写虚函数把基类继承来的虚函数的地址给覆盖了,


例子

没有虚函数

#include <iostream>
#include <typeinfo>   // typeid(name).name()
using namespace std;




class A
{
public:
A(int data) :ma(data) {}
void show() { cout << "A::show ma:" << ma << endl; }
protected:
int ma;
};
class B : public A
{
public:
B(int data) : mb(data), A(data) {}
void show() { cout << "B::show ma:" << ma << " mb:" << mb << endl; }
private:
int mb;
};
int main()
{
A a(10);
B b(20);


A *p = &b;
p->show();   // Derive  自己的成员+基类::成员  A::show  
/*
show是普通函数,在这里是静态绑定
call A::show
*/
//派生类对象的内存大小  8  
cout << sizeof(b) << endl;
//指针的类型 A*  A*
cout << typeid(p).name() << endl;
//指针指向对象的类型  A  B   不能识别静态类型了  p的类型里面有虚函数=》RTTI
cout << typeid(*p).name() << endl;


return 0;
}

结果:

A::show ma :20  mb:20

8

class A*

class A


有虚函数

class A
{
public:
A(int data) :ma(data) {}
virtual void show() { cout << "A::show ma:" << ma << endl; }
protected:
int ma;
};
class B : public A
{
public:
B(int data) : mb(data), A(data) {}
void show() { cout << "B::show ma:" << ma << " mb:" << mb << endl; }
private:
int mb;
};
int main()
{
A a(10);
B b(20);


A *p = &b;
p->show();   // Derive  自己的成员+基类::成员   B::show
/*
 

show是虚函数,在这里就要动态绑定/运行时期的绑定了
mov eax, dword ptr[p]
mov ecx, dword ptr[eax]
call ecx
*/


//派生类对象的内存大小   12
cout << sizeof(b) << endl;
//指针的类型 A*  A
cout << typeid(p).name() << endl;
//指针指向对象的类型  A  B   不能识别静态类型了  p的类型里面有虚函数=》RTTI
cout << typeid(*p).name() << endl;


return 0;
}

结果:

B::show ma :20  mb:20

12

class A*

class B

7.什么叫RTTI?RTTI  run-time type informaition 运行时的类型的识别

RTTI存在虚函数表中:当一个类有虚函数,它编译的时候产生一个Vtable ,虚函数表存放了虚函数的地址,Vptr 相对内存起始地址的偏移量,以及RTTI指针(和类型一一对应)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值