成员函数与虚函数

C++语言中,类将成员函数分为两种:
一种是基类希望派生类进行覆盖的函数,被定义为虚函数(virtual);
另一种是基类希望派生类直接继承而不对其进行修改的函数。

两种函数的区别:

  1. 解析过程不同:成员函数如果没有被声明为虚函数,它的解析发生在编译时,而不是运行时。因为虚函数在运行时才知道要调用哪个版本的函数,它是执行动态绑定;
  2. 关于this指针

public,private和protected

派生类有权访问public和protected,但是没办法访问private的成员;
protected只能被派生类访问,禁止其他用户访问。

重构

重新设计类的体系,以便将操作和数据从一个类移动到另一个类。
比如基类Qoute和其派生类Bulk_quote,我们定义一个抽象基类Disc_quote实现几种不同的打折策略,Bulk_quote就符合这几种策略之一。从而让Bulk_quote类继承Disc_quote,Disc_quote继承基类Qoute。此时Bulk_quote对象可以包含三个子对象,一个是直接基类Disc_quote子对象,一个是间接基类Quote子对象以及空的Bulk_quote部分。

class Bulk_quote : public Disc_quote{
public:
    Bulk_quote() = default;
    Bulk_quote(const std::string& book, double price,
              std::size_t qty, double disc) : 
              Disc_quote(book, price, qty, disc) { }
    double net_price(std::size_t) const override;
};

Note that : 即使我们修改了Bulk_quote和Quote类的继承关系,那些使用这些类的代码也无需修改,但需要重新编译。

重载,虚函数与作用域

声明在内层作用域中的函数无法重载声明在外层作用域中的函数,即使他们具有相同的函数名。如派生类会隐藏基类中同名的函数。
对于虚函数而言,在基类和派生类中必须具有相同的参数列表,否则就会被派生类隐藏起来。
例如下面的代码

class Base{
...
virtual int fcn();
};
class D1: public Base{
    int fcn(int);  //函数参数不同,将基类Base中的fcn()隐藏
    virtual void f2();
};
class D2:public D1{
    int fcn(int);  //非虚函数,隐藏D1中的fcn(int)
    int fcn();  //覆盖了Base的虚函数fcn
    void f2();  //覆盖D1中的f2
};

//使用时,定义三个类的对象以及Base类指针
Base baseobj; D1 d1obj; D2 d2obj;
Base* pb=&baseobj; pd1=&d1pbj; pd2=d2obj;
pb->fcn();  //调用虚函数Base::fcn()
pd1->fcn(); //调用虚函数Base::fcn() 动态绑定时D1中找不到就向上层作用域找
pd2->fcn(); //调用虚函数D2::fcn()
pd1->f2(); //错误,D1和Base中均没有f2()

//定义D1类指针和D2类指针
D1* pd_1=&d1obj; D2* pd_2=&d2obj;
pd_1->f2(); //调用虚函数D1::f2();
pd_2->f2(); //调用虚函数D2::f2()

调用非虚函数时,不会发生动态绑定,实际调用的函数版本由指针的静态类型来决定。

//自己能否根据上面的类来写一个例子?
全部评论

相关推荐

投递华为等公司10个岗位
点赞 评论 收藏
转发
点赞 收藏 评论
分享
牛客网
牛客企业服务