c++ virtual总结
来源:互联网 发布:淘宝店铺代运营广告 编辑:程序博客网 时间:2024/06/05 00:19
链接:http://blog.csdn.net/chief1985/article/details/4755560
c++是一门面向对象的语言,但是它和c#,java不同,它没有反射机制。没有反射机制使得c++在语言的一些设计方面与其他语言有点不一样,主要体现在智能化方面,许多东西得程序员明确指定,例如本文要讲的virtual关键字。virtual是在运行时才体现的,而c++在运行时无法使用反射来确定当前类的父类是否有此方法,此方法是否被重载等信息,所以必须在写代码时用virtual来明确指明,然后通过编译器做一些特殊处理(也就是使用虚表)。
我们见到virtual最多的地方是在c++里面的多态实现。
- // dynamic_poly.h
- #include <iostream>
- // 公共抽象基类Vehicle
- class Vehicle
- {
- public:
- virtual void run() const = 0;
- };
- // 派生于Vehicle的具体类Car
- class Car: public Vehicle
- {
- public:
- virtual void run() const
- {
- std::cout << "run a car/n";
- }
- };
- // 派生于Vehicle的具体类Airplane
- class Airplane: public Vehicle
- {
- public:
- virtual void run() const
- {
- std::cout << "run a airplane/n";
- }
- };
- // dynamic_poly_1.cpp
- #include <iostream>
- #include <vector>
- #include "dynamic_poly.h"
- // 通过指针run任何vehicle
- void run_vehicle(const Vehicle* vehicle)
- {
- vehicle->run(); // 根据vehicle的具体类型调用对应的run()
- }
- int main()
- {
- Car car;
- Airplane airplane;
- run_vehicle(&car); // 调用Car::run()
- run_vehicle(&airplane); // 调用Airplane::run()
- }
上面的例子来自于http://www.vckbase.com/document/viewdoc/?id=948,这篇文章里面还提到了多态的一些别的例子。关于多态的文章还有孟岩写的一篇http://blog.csdn.net/wuliming_sc/archive/2009/01/31/3855906.aspx,可以看看。
在很多多态的例子中,我们都可以看到将基类的方法声明为纯虚函数(virtual void run() const = 0;),这样可以要求子类必须实现这个方法,同时可以体现面向接口编程。
对于使用了virtual之后编译器会做些什么,我觉得用代码更容易说明问题。下面的例子来自http://www.cppblog.com/zhangyq/archive/2009/06/13/87597.html。
1 编译器会为这个类的虚函数添加一个虚表,类似下面的:
// Pseudo-code (not C++, not C) for a static table defined within file Base.cpp
// Pretend FunctionPtr is a generic pointer to a generic member function
// (Remember: this is pseudo-code, not C++ code)
FunctionPtr Base::__vtable[5] = {
&Base::virt0, &Base::virt1, &Base::virt2, &Base::virt3, &Base::virt4
};
2 然后增加一个指向虚表的指针为每一个类对象,这个指针是隐藏的
// Your original C++ source code
class Base {
public:
...
FunctionPtr* __vptr; ← supplied by the compiler, hidden from the programmer
...
};
3 编译器在构造中初始化这个指针
Base::Base(...arbitrary params...)
: __vptr(&Base::__vtable[0]) ← supplied by the compiler, hidden from the programmer
...
{
...
}
在派生类中,它也会增加一个隐藏的虚表,但是它可以overrides基类的虚函数如:
// Pseudo-code (not C++, not C) for a static table defined within file Der.cpp
// Pretend FunctionPtr is a generic pointer to a generic member function
// (Remember: this is pseudo-code, not C++ code)
FunctionPtr Der::__vtable[5] = {
&Der::virt0, &Der::virt1, &Der::virt2, &Base::virt3, &Base::virt4
};
从上面的代码我们可以非常容易的划出class的结构图,当然可以用/d1reportSingleClassLayout来显示class的布局图(http://blog.csdn.net/chief1985/archive/2009/10/23/4720191.aspx)。
使用virtual的地方还有虚拟继承和虚拟析构函数。
虚拟继承的例子如下,来自http://blog.csdn.net/wuliming_sc/archive/2009/01/31/3855607.aspx:
- class Point2d{
- public:
- //...
- protected:
- float _x;
- float _y;
- };
- class Vertex : public virtual Point2d{
- public:
- //...
- protected:
- Vertex *next;
- };
- class Point3d : public virtual Point2d{
- public:
- //...
- protected:
- float _z;
- };
- class Vertex3d: public Vertex, public Point3d{
- public:
- //...
- protected:
- float mumble;
- };
使用虚拟继承一般都是出现了菱形继承(c++允许多重继承),这种情况下若不使用虚拟继承,便会导致以下情况:
1.公共基类子对象的重复创建问题。
2.成员函数的名字冲突问题
3. 数据成员的名字冲突问题
出现虚拟析构函数的地方也是在多态的时候,如果不使用虚拟析构函数,将会导致子类的析构函数没被调用,例子可以参考http://blog.csdn.net/starlee/archive/2006/03/09/619827.aspx。
- c++virtual
- c++ virtual总结
- C++ virtual使用总结
- c++ virtual总结
- C# virtual 四点总结
- Virtual的一些总结
- c++ virtual总结
- virtual关键字用法总结
- C++ virtual 总结
- c++ virtual总结
- c++ virtual总结
- C++ Virtual总结
- Virtual Disk 项目总结
- friend static virtual 总结
- 关于C#:abstract,virtual
- C++Virtual详解
- Virtual & Abstract (C++)
- C#virtual override new
- [leetcode] Combination Sum
- Tieria iOS9 新增 UIStackView 官方文档翻译
- 使用Android Studio进行单元测试
- <Unity UGUI><EasyTouch> 使用EasyTouch, 摇杆在Dynamic模式下,点击UI控件也会弹出的问题解决
- 【转】HTTP协议详解
- c++ virtual总结
- 专家纵论智能机器社会的风险与解决方案
- C标准I/O缓冲区:全缓冲和行缓冲
- 实现InstaMaterial概念设计 - 完结篇
- VS中建立dll和lib项目总结
- 集电极开路输出、开漏输出、推挽输出
- spring mvc messageConverters及406等问题
- clog,cout,cerr 输出机制
- Java之CyclicBarrier使用