虚函数和多态

来源:互联网 发布:mac目录结构 编辑:程序博客网 时间:2024/05/29 21:17


定义:类的成员函数前面加virtual关键字
虚函数重写:子类定义了一个与父类完全形同的虚函数,子类的函数重写(覆盖)父类的虚函数
隐藏:作用域不同,
注意:虚函数和虚继承关键字一样,但意义完全不同

多态:当使用基类的指针或引用调用重写的虚函数时,当指向父类调用的就是父类的虚函数,指向子类调用的就是子类的虚函数
构成多态的条件:
     1.  虚函数重写
     2. 必须是父类的指针或引用
调用原则:
    如果构成多态,跟对象有关;不构成多态,跟类型有关
重载:在同一作用域中,函数名相同,参数列表不同,返回值可以不同
重定义/隐藏:在不同作用域中(分别在基类和派生类),函数名相同,在基类和派生类中只要不构成重写就是重定义
重写/覆盖:在不同作用域中(分别在基类和派生类),函数名相同,参数相同,返回值相同(协变除外),基类函数必须有virtual关键字,访问修饰符可以不同
总结:
1. 派生类重写基类的虚函数实现多态,要求函数名、参数列表、返回值完全相同。(协变除外) 
    协变:如果是父类的指针或引用,返回值可以不同,也能构成多态
2. 基类中定义了虚函数,在派生类中该函数始终保持虚函数的特性。
3. 只有类的成员函数才能定义为虚函数。(和虚表有关) 
4. 静态成员函数不能定义为虚函数。 
5. 如果在类外定义虚函数,只能在声明函数时加virtual,类外定义函数时不能加virtual。 
6. 构造函数不能为虚函数,虽然可以将operator=定义为虚函数,但是最好不要将operator=定义为虚函数,因为容易使用时容易引 起混淆。 
7. 不要在构造函数和析构函数里面调用虚函数,在构造函数和析构函数中,对象是不完整的,可能会发生未定义的行为。(父类调用构造函数可能会形成多态调到子类,先构造父类再构造子类,子类构造还没有初始化) 
8. 最好把基类的析构函数声明为虚函数。(另外析构函数比较特殊,因为派生类的析构函数跟基类的析构函数名称不一样,但 是构成覆盖,这里是因为编译器做了特殊处         理)
内联函数不可以是虚函数,因为内联函数没有地址,会被展开;构造函数和静态成员函数不可以是虚函数,因为静态成员是共有的,定义成虚函数要放在虚表中,通过对象调用,静态成员没有this 指针。
一个对象访问普通成员和虚函数哪个更快?
       不一定,如果虚函数构成多态的条件,访问普通成员函数更快,否则一样快。
在什么情况下,析构函数需要定义成虚函数?
       基类的析构函数,在不清理解决方案的情况下,可能会造成内存泄漏。
纯虚函数:
       在成员函数的形参后面写上=0,则成员函数为纯虚函数。包含纯虚函数的类叫做抽象类(也叫接口类),抽象类不能实例化出对象。纯虚 函数在派生类中重新定义以后,派生类才能实例化出对象。
友元与继承:
        友元关系不能继承,也就是说基类友元不能访问子类私有和保护成员。
继承与静态成员:
        基类定义了static成员,则整个继承体系里面只有一个这样的成员。无论派生出多少个子类,都只有一个static成员实例。 



        


原创粉丝点击