C++ Virtual And Pure Virtual Explained
时间:2022-05-07
本文章向大家介绍C++ Virtual And Pure Virtual Explained,主要内容包括Virtual、Pure Virtual、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。
Virtual
Virtual Function是成员函数,其行为在派生类中被覆盖。与非虚函数不同的是,即使没有关于类的实际类型的编译时信息,也会保留重写的行为。如果派生类使用指针或者对基类的引用进行处理,则对被覆盖的虚函数的调用将调用派生类中定义的行为。
#include <iostream>
struct Base {
virtual void f() {
std::cout << "basen";
}
};
struct Derived : Base {
void f() override { // 'override' is optional
std::cout << "derivedn";
}
};
int main()
{
Base b;
Derived d;
// virtual function call through reference
Base& br = b; // the type of br is Base&
Base& dr = d; // the type of dr is Base& as well
br.f(); // prints "base"
dr.f(); // prints "derived"
// virtual function call through pointer
Base* bp = &b; // the type of bp is Base*
Base* dp = &d; // the type of dp is Base* as well
bp->f(); // prints "base"
dp->f(); // prints "derived"
// non-virtual function call
br.Base::f(); // prints "base"
dr.Base::f(); // prints "base"
}
//输出
base
derived
base
derived
base
base
虚函数使其类成为多态基类,派生类可以覆盖虚函数。 通过基类指针/引用调用的虚函数将在运行时解析。 也就是说,使用对象的动态类型而不是静态类型。静态类型是指不需要考虑表达式的执行期语义,仅分析程序文本而决定的表达式类型。静态类型仅依赖于包含表达式的程序文本的形式,而在程序运行时不会改变。动态类型是由一个左值表达式表示的左值所引用的最终派生对象的类型。 大致可以这么理解:
- 静态类型:对象在声明时采用的类型,在编译期既已确定。
- 动态类型:通常是指一个指针或引用目前所指对象的类型,是在运行期决定的。
- 静态绑定:绑定的是静态类型,所对应的函数或属性依赖于对象的静态类型,发生在编译期。
- 动态绑定:绑定的是动态类型,所对应的函数或属性依赖于对象的动态类型,发生在运行期。
Pure Virtual
抽象类是定义或继承至少一个最终覆盖纯虚函数的类,一个纯虚函数隐含的使其自己的类被定义为抽象类,抽象类不能被实例化,只能通过派生类来覆盖实现所有继承的纯虚函数,如果派生类不覆盖实现所有的纯虚函数,那么程序编译不通过报错。何为纯虚函数?格式如下: declarator virt-specifier(optional) = 0 eg: virtual func(optional) = 0; =0只能出现在声明标识符之后或者可选标识符(virtual、final)之后,不能出现在成员函数定义中。
#include <iostream>
struct Base {
virtual int g();
virtual ~Base() {}
};
struct A : Base {
// ok, declares three member virtual functions, two of them pure
virtual int f() = 0;
//override代表派生类覆盖父类g()方法
virtual int g() override = 0;
virtual int h();
// ok, destructor can be pure too
virtual ~A() = 0;
// error: pure-specifier on a function definition
virtual int b()=0 {}
};
//输出为
virtual int b()=0 {} error: initializer on function does not look like a pure-specifier
struct Abstract {
virtual void f() = 0; // pure virtual
virtual void g() {}; // non-pure virtual
~Abstract() {
g(); // okay, calls Abstract::g()
// f(); // undefined behavior!
Abstract::f(); // okay, non-virtual call
}
};
//definition of the pure virtual function
void Abstract::f() { std::cout << "A::f()n"; }
struct Concrete : Abstract {
void f() override {
Abstract::f(); // OK: calls pure virtual function
}
void g() override {}
~Concrete() {
g(); // okay, calls Concrete::g()
f(); // okay, calls Concrete::f()
}
};
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Java基础
- 广度优先遍历--选课的智慧
- paddlepaddle目标检测之水果检测(yolov3_mobilenet_v1)
- 【每日一题】41. First Missing Positive
- springmvc之第一个springmvc程序
- python小例子(一)
- springmvc之RequestMapping注解既可以修饰类也可以修饰方法
- hadoop伪分布式之配置历史服务器
- 广度优先遍历--合法的括号
- hadoop伪分布式之配置日志聚集
- Kettle构建Hadoop ETL实践(二):安装与配置
- WKWebView加载沙盒HTML
- 【python-leetcode480-双堆】滑动窗口的中位数
- 虚拟机--python环境配置
- 利用装饰器计算函数运行的时间