多态小Tips

目录

1.虚函数

 2. 设置为虚函数

 3.多态

 4.多态类型的调用  

 5.抽象类和纯虚函数

 6.虚表

 7.练习题 


1.虚函数

虚函数是被virtual修饰的类成员函数

virtual关键字只在声明时加上,在类外实现时不能加。

 

 static和virtual不能同时使用。

 2. 设置为虚函数

 首先,虚函数必须是类成员函数。

                                            成员函数 VS 非成员函数

 成员函数简单来说就是类中定义的函数,作为一个类的成员。

 而非成员函数就是不在类中定义的函数,其中友元函数就属于非成员函数。(友元函数可以   直接访问类的私有成员,它是定义在类外部的普通函数,不属于任何类

1.因此友元函数不能设置为虚函数。

2.静态成员函数不能设置为虚函数。

原因一:static和virtual不能同时使用 

原因二:静态成员函数与具体对象无关,属于整个类,核心关键是没有隐藏的this指针,可以通过类名::成员函数名 直接调用,此时没有this无法拿到虚表,就无法实现多态,因此不能设置为虚函数

3.父类的析构函数建议设置为虚函数 

 这样动态释放父类指针所指的子类对象时,能够达到析构的多态

 3.多态

1. 多态分为编译时多态和运行时多态,也叫早期绑定和晚期绑定,还被叫做静态多态和动态多态。

2.编译时多态通过函数重载模板来实现的。

3.运行时多态,还被叫做覆盖,重写,基于虚函数机制实现多态功能

 4.多态类型的调用  

判断正误:

在编译期间,通过传递不同类的对象,编译器选择调用不同类的虚函数 (x)

解释:不是在编译期,而应该在运行期间,编译期间,编译器主要检测代码是否违反语法规则,此时无法知道基类的指针或者引用到底引用那个类的对象,也就无法知道调用那个类的虚函数。在程序运行时,才知道具体指向那个类的对象,然后通过虚表调用对应的虚函数,从而实现多态。 

 5.抽象类和纯虚函数

纯虚函数可以有函数体(函数实现),但是意义不大,因为抽象类没办法实例化对象。

 抽象类可以定义为指针,而且经常这样做,其目的就是用父类指针指向子类从而实现多态

 6.虚表

多继承的时候,可能会有多张虚表 

虚表时在编译期间生成的。

当定义多个对象时,同一个类的虚表是共享的。

当子类的虚函数重写之后,但是该虚函数为私有(private)时,若构成多态,也能访问的了,因为多态仅仅是用子类虚函数的地址覆盖虚表,实际要调用的时候直接去虚表里找地址就行了,不受private的限制。

 7.练习题 

//以下程序输出结果是( )
class A
{
public:
    A() :m_iVal(0) { test(); }

    virtual void func() { std::cout << m_iVal <<endl; }

    void test() { func(); }
public:
    int m_iVal;
};

class B : public A
{
public:
    B() { test(); }
    virtual void func()
    {
        ++m_iVal;
        std::cout << m_iVal <<" ";
    }
};
int main()
{
    A* p = new B;

    p->test();

    return 0;
}

A.1 0

B.0 1

C.0 1 2

D.2 1 0

E.不可预期

F. 以上都不对

分析:new B时先调用父类A的构造函数,执行test()函数,在调用func()函数,由于此时还处于构造B对象阶段,多态机制还没有生效,所以,此时执行的func函数为父类的func函数,打印0,构造完父类后执行子类构造函数,又调用test函数,然后又执行func(),由于父类已经构造完毕,虚表已经生成,func满足多态的条件,所以调用子类的func函数,对成员m_iVal加1,进行打印,所以打印1, 最终通过父类指针p->test(),也是执行子类的func,所以会增加m_iVal的值,最终打印2, 所以答案为C 0 1 2

变式:将A*p=new B改为B*p=new B,结果又如何?

前面还是一样,先打印0,再打印1,然后通过子类指针p->test() ,但是test()是父类作用域里的,只是子类继承下来的,实际上test()函数里还隐藏一个t父类的this指针,再由这个this指针去调用func,而func是虚函数,并且子类也进行了重写,而且还是父类的this指针调用,满足多态,所以还是执行子类的func,增加m_iVal的值,最终打印2, 所以答案还是C 0 1 2

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值