Ordinarily, if we do not use a function, we do not need to supply a definition of the function.

However, we must define every virtual function, regardless of whether it is used, bacuase compiler has no way to determine whether a virtual function is used.

    Quote base("0-201-1", );
print_total(cout, base, ); // call Quote::net_print Bulk_quote derived("0-201-2", , , 0.19);
print_total(cout, derived, ); // call Bulk_quote::net_print base = derived;   // copy the Quote part of derived into base
base.net_print(); // call Quote::net_print

When we call a virtual function on an expression that has a plain type - nonreference and nonpointer -- type, that call is bound at compile time. Both base and derived are plain - nonreference and nonpointer - type

Virtual are resolved at run time only if the call is called through a reference or pointer.

When a derived class override a virtual function, it may, but is not requied to, repeat the virtual keyword. Once a function is declared as virtual, remaining virtual in all the derived classes implicitly.

Virtual functions that have default arguments should use the same value in the base and derived classes.

In some cases, we want to force to call a particular version of the virtual.

    double discounted = baseP->Quote::net_price();

Call the Quote version net_price regardless of the type of object to which baseP actually points. This call can be resolved at compile time.

We can specify a virtual function as a pure virtual function by writing =0 in the place of the function body. The =0 appear only on the declaration of the virtual function in the class body.

A class containing( or inherit without overriding) a pure virtual function is known as an abstract class. We cannot (directly) create a object of a type that is an abstract class.

A abstract class declares the interface of subsequent class to override.

class Disc_quote : public Quote{
public:
Disc_quote() = default;
Disc_quote(const string & bookNo, double price, size_t qty, double disc) : Quote(bookNo, price), quantity(qty, discount(disc) { }
double net_price(size_t) const = ; // an pure virtual function
protected:
size_t quantity = ;
double discount = 0.0;
} Disc_quote discount; // error: define an Disc_quote object

Now we can reimplement Bulk_quote to inherit from Disc_quote rather than inherit directly from Quote:

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

Reference:

C++ Primer, Fifth Edition, chapter 15 Object-Oriented Programming

[C++] OOP - Virtual Functions and Abstract Base Classes的更多相关文章

  1. python 用abc模块构建抽象基类Abstract Base Classes

    见代码: #!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/08/01 16:58 from abc import ABCMet ...

  2. virtual base classes

    virtual base classes用来实现菱形继承解决多个重复subobject的问题 //: C09:VirtualBase.cpp // Shows a shared subobject v ...

  3. 纯虚函数(pure virtual function )和抽象类(abstract base class)

    函数体=0的虚函数称为“纯虚函数”.包含纯虚函数的类称为“抽象类” #include <string> class Animal // This Animal is an abstract ...

  4. Virtual functions in derived classes

    In C++, once a member function is declared as a virtual function in a base class, it becomes virtual ...

  5. Standard C++ Programming: Virtual Functions and Inlining

    原文链接:http://www.drdobbs.com/cpp/standard-c-programming-virtual-functions/184403747 By Josée Lajoie a ...

  6. [CareerCup] 13.3 Virtual Functions 虚函数

    13.3 How do virtual functions work in C++? 这道题问我们虚函数在C++中的工作原理.虚函数的工作机制主要依赖于虚表格vtable,即Virtual Table ...

  7. [译]GotW #5:Overriding Virtual Functions

       虚函数是一个很基本的特性,但是它们偶尔会隐藏在很微妙的地方,然后等着你.如果你能回答下面的问题,那么你已经完全了解了它,你不太能浪费太多时间去调试类似下面的问题. Problem JG Ques ...

  8. virtual方法和abstract方法

    在C#的学习中,容易混淆virtual方法和abstract方法的使用,现在来讨论一下二者的区别.二者都牵涉到在派生类中与override的配合使用. 一.Virtual方法(虚方法) virtual ...

  9. C#面向对象基础:virtual方法,abstract方法,区别

    virtual 关键字用于修饰方法.属性.索引器或事件声明,并使它们可以在派生类中被重写.默认情况下,类中的方法是非虚的,非虚的方法不能在子类中被覆盖(override),但是可以隐藏(new),但这 ...

随机推荐

  1. DB数据源之SpringBoot+MyBatis踏坑过程(三)手工+半自动注解配置数据源与加载Mapper.xml扫描

    DB数据源之SpringBoot+MyBatis踏坑过程(三)手工+半自动注解配置数据源与加载Mapper.xml扫描 liuyuhang原创,未经允许禁止转载    系列目录连接 DB数据源之Spr ...

  2. eclipse官方下载地址

    下载地址:  https://www.eclipse.org/downloads/packages/release/Luna/SR2 选择不同版本

  3. awk命令用法

    awk:把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理,是一个强大的文本分析工具,在对数据分析并生成报告时很有优势. awk有3个不同版本: awk.nawk和gawk, ...

  4. ubuntu系统的软件包管理工具

    ubuntu系统的软件包管理工具有两种,一种是离线管理,另一种是在线管理 1.离线管理 dpkg工具可以对本地存放的deb安装包进行安装,卸载,查看状态等. dpkg -i app_name_vers ...

  5. Maven DebugConfiguration配置运行内存

    -Xms256M -Xmx512M -XX:PermSize=256m -XX:MaxPermSize=512m

  6. php的基础知识(四)

    14.数组: 索引数组: 下标就是数字开始的. $arr = ['a','b','c',1,2,3]; 关联数组: $arr = [ 'a' => 'b', 'c' => 'd'; 'e' ...

  7. 【MYSQL笔记】

    1.去重取出id最小的记录 tip:在laravel框架里配置信息database设置了'strict' => true,所以在groupBy时只能select出groupBy后的字段,当想搜索 ...

  8. 初学者:__init__.py文件的作用

    __init__.py 文件的作用及意义 __init__.py文件是一个包必须的文件,即使它是空的,但也是必须的,如果没有这个文件,python将不会把该文件夹当做一个package,而仅仅是一个d ...

  9. MFC非模态添加进程控件方法二(自定义消息方法)

    以下内容有大部分转载自CSDN,经过自己整理完成. 该文主要的方法为在非模态对话框中自定义一组消息函数,然后在主窗口中开辟一个线程通过线程把消息传递给子窗口进行更新. 在子窗口类中定义消息如下: /* ...

  10. Python 爬虫 (一)

    爬: 爬一个网站需要几步? 确定用户的需求 根据需求,寻找网址 读取网页 urllib request requests 定位并提取数据 正则 xpath beautiful soup 存储数据 my ...