• 欢迎光临~

# 为什么需要virtual

```#include <stdio.h>
class Point2d {
public:
Point2d(int x = 0, int y = 0): _x(x), _y(y) {}
void print() const { printf("Point2d(%d, %d)n", _x, _y); }
protected:
int _x;
int _y;
};
class Point3d : public Point2d {
public:
Point3d(int x = 0, int y = 0, int z = 0):Point2d(x, y), _z(z) {}
void print() const { printf("Point3d(%d, %d, %d)n", _x, _y, _z); }
protected:
int _z;
};
int main() {
Point2d point2d;
Point3d point3d;
point2d.print();        //outputs: Point2d(0, 0)
point3d.print();        //outputs: Point3d(0, 0, 0)
return 0;
}```

```void print(const Point2d &point) {
point.print();
}
int main() {
Point2d point2d;
Point3d point3d;
print(point2d);       //outputs: Point2d(0, 0)
print(point3d);       //outputs: Point2d(0, 0)
return 0;
}```

```class Point2d {
public:
virtual void print() const { printf("Point2d(%d, %d)n", _x, _y); }
};
int main() {
Point2d point2d;
Point3d point3d;
print(point2d);       //outputs: Point2d(0, 0)
print(point3d);       //outputs: Point3d(0, 0, 0)
return 0;
}```

# virtual 类的内存布局

```class Point2d {
public:
Point2d(int x = 0, int y = 0): _x(x), _y(y) {}
virtual void print() const { printf("Point2d(%d, %d)n", _x, _y); }
virtual int z() const { printf("Point2d get z: 0n"); return 0; }
virtual void z(int z) { printf("Point2d set z: %dn", z); }
protected:
int _x;
int _y;
};
class Point3d : public Point2d {
public:
Point3d(int x = 0, int y = 0, int z = 0):Point2d(x, y), _z(z) {}
void print() const { printf("Point3d(%d, %d, %d)n", _x, _y, _z); }
int z() const { printf("Point3d get z: %dn", _z); return _z; }
void z(int z) { printf("Point3d set z: %dn", z); _z = z; }
protected:
int _z;
};```

真实内存布局是否如上图所示，很简单，我们一验便知：

```int main() {
typedef void (*VF1) (Point2d*);
typedef void (*VF2) (Point2d*, int);
Point2d point2d(11, 22);
intptr_t *vtbl2d = (intptr_t*)*(intptr_t*)&point2d;
((VF1)vtbl2d[0])(&point2d);       //outputs: Point2d(11, 22)
((VF1)vtbl2d[1])(&point2d);       //outputs: Point2d get z: 0
((VF2)vtbl2d[2])(&point2d, 33);   //outputs: Point2d set z: 33
Point3d point3d(44, 55, 66);
intptr_t *vtbl3d = (intptr_t*)*(intptr_t*)&point3d;
((VF1)vtbl3d[0])(&point3d);       //outputs: Point3d(44, 55, 66)
((VF1)vtbl3d[1])(&point3d);       //outputs: Point3d get z: 66
((VF2)vtbl3d[2])(&point3d, 77);   //outputs: Point3d set z: 77
return 0;
}```

virtual 析构函数

```class Point {
public:
~Point() { printf("~Pointn"); }
};
class Point2d : public Point {
public:
~Point2d() { printf("~Point2d"); }
};
class Point3d : public Point2d {
public:
~Point3d() { printf("~Point3d"); }
};
int main() {
Point *p1 = new Point();
Point *p2 = new Point2d();
Point2d *p3 = new Point2d();
Point2d *p4 = new Point3d();
Point3d *p5 = new Point3d();
delete p1;      //outputs: ~Point
delete p2;      //outputs: ~Point
delete p3;      //outputs: ~Point2d~Point
delete p4;      //outputs: ~Point2d~Point
delete p5;      //outputs: ~Point3d~Point2d~Point
return 0;
}```

```//除Point析构声明为virtual外，其余均不变
int main() {
Point *p1 = new Point();
Point *p2 = new Point2d();
Point2d *p3 = new Point2d();
Point2d *p4 = new Point3d();
Point3d *p5 = new Point3d();
delete p1;      //outputs: ~Point
delete p2;      //outputs: ~Point2d~Point
delete p3;      //outputs: ~Point2d~Point
delete p4;      //outputs: ~Point3d~Point2d~Point
delete p5;      //outputs: ~Point3d~Point2d~Point
return 0;
}```

virtual析构函数版本，决定继承体系中析构函数链调用的因素是指针的实际类型：析构函数的调用从指针指向的实际类型的类开始，依次调用其父类析构函数。

# 什么时候需要 virtual

```#include <stdio.h>
#include <time.h>
struct Point2d {
int _x, _y;
};
struct VPoint2d {
virtual ~VPoint2d() {}
int _x, _y;
};
template <typename T>
T sum(const T &a, const T &b) {

T result;
result._x = a._x + b._x;
result._y = a._y + b._y;
return result;
}
template <typename T>
void test(int times) {
clock_t t1 = clock();
for (int i = 0; i < times; ++i) {
sum(T(), T());
}
clock_t t2 = clock();
printf("clocks: %lun", t2 - t1);
}
int main() {
test<Point2d>(1000000);
test<VPoint2d>(1000000);
return 0;
}```

1.在继承中使用多态能力的时候，需要使用virtual functions机制；

2.基类指针指向子类实例的时候，需要使用virtual析构函数；