C++ 中的静态绑定和动态绑定

C++ 在面向对象编程中,有着静态绑定动态绑定的定义,为了了解这两个概念,首先先简单阐述一些名词:

  • 静态类型:对象在声明时使用的类型,在编译期就已经确定
  • 动态类型:指针变量或引用变量所指向对象的类型,在运行期才能确定
  • 静态绑定:绑定的是静态类型,对象的函数和属性依赖于绑定的静态类型,发生在编译期
  • 动态绑定:绑定的是动态类型,对象的函数和属性依赖于绑定的动态类型,发生在运行期

而非虚函数一般都是静态绑定,虚函数则是动态绑定

举一个例子来说明静态类型和动态类型:

class Shape {
    
    //用于描述几何形状的类
public:
    enum ShapeColor  {
    
     Red, Green, Blue };
    //所有形状都必须提供一个函数来绘制自己
    virtual void draw(ShapeColor color = Red) const = 0;
	void draw() const;
    ...
};
class Rectangle : public Shape {
    
    
public: 
    //注意,与基类的默认参数值不同
    virtual void draw(ShapeColor color = Green) const;
    ...
};
class Circle : public Shape  {
    
    
public:
    //没有默认参数值,调用该函数一定要赋予参数,因为静态绑定下,这个函数并不从其基类继承默认参数值
    //但若以指针或引用调用此函数,可以不指定参数值,因为动态绑定下,这个函数会从其基类继承默认参数值
    virtual void draw(ShapeColor color) const;
    ...
};

int main(){
    
    
	// 静态类型都为 Shape* 。注意,不论它们真正指向什么,它们的静态类型都是 Shape*
	Shape* ps;					// ps 没有指向,所以它没有动态类型
	Shape* pNull = nullptr;		// pNull 没有指向,所以它没有动态类型
	Shape* pc = new Circle;		// pc 的动态类型为 Circle*
	Shape* pr = new Rectangle;	// pr 的动态类型为 Rectangle*
	ps = pc;					// ps 的动态类型如今是 Circle*
	ps = pr;					// ps 的动态类型如今是 Rectangle*
	
	return 0;
}

由于 虚函数 是动态绑定的,所以调用一个 虚函数 时,究竟调用哪个函数取决于发出调用的那个对象的 动态类型

pc->draw(Shape::Red);	// 调用 Circle::draw(Shape::Red)
pr->draw(Shape::Red);	// 调用 Rectangle::draw(Shape::Red)
pNull->drwa();			// 调用 Shape::draw() ,空指针可以调用非虚函数,因为静态绑定在编译期就确定了,和指针空不空没关系

总结一下静态绑定和动态绑定的区别:

  1. 静态绑定发生在编译期,动态绑定发生在运行期
  2. 对象的动态类型可以更改,但是静态类型无法更改
  3. 要想实现动态,必须使用动态绑定
  4. 在继承体系中只有虚函数使用的是动态绑定,其他的全部是静态绑定;

猜你喜欢

转载自blog.csdn.net/qq_34168988/article/details/125787782