当前位置:   article > 正文

对C++多重继承中函数名称查找的理解_多重继承如何快速寻找到原函数

多重继承如何快速寻找到原函数
	class A1
	{
	public:
			virtual void P() const = 0;
			void print() const { std::cout << "A1\n"; };
	};

	class B1 : public A1
	{
	public:
		void P() const override final { print(); }
		void print() const { std::cout << "B1\n"; }
	};

	class B2 : public B1
	{
	public:
		virtual void print() const  { std::cout << "B2\n"; }
	};

	class C1 : public B2
	{
	public:
		void print() const  { std::cout << "C1\n"; }
	};

	int main()
	{
	
		B1 b1;
		B2 b2;
		C1 c1;

		A1* a1 = &b1;
		A1* a2 = &b2;
		A1* a3 = &c1;
		B1* b11 = &c1;
		B2* b22 = &c1;

		a1->P(); // 1
		a2->P(); // 2
		a3->P(); // 3
		b11->P(); // 4
		b22->P(); // 5

		return 0;
	}
	
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

上述的输出全部都是"B1"。

原因是表达式1在执行名称查找时,首先去A1类中查找(因为a1的类型显式类型是A1指针),发现P()是一个虚函数,因此就会从a1对象中的虚函数表中查找P()的函数指针,发现此函数指针指向的是B1::P()。然后B1::P()中调用了print(),因此直接在类B1中查找print(),如果找不到的话,编译器会继续到类B1作用域的上层,即类A1的作用域中查找print()名称(所以如果你把B1::print()注释掉的话,最终结果都是"A1"),编译器在B1中找到了print(),并发现它不是虚函数,因此不会去a1对象的虚函数表中查找print(),因此最终调用的就是B1::print()

表达式2和3在执行名称查找时,跟表达式1一样,因为P()是虚函数,所以会从对应的对象的虚函数表中查找;

表达式4执行名称查找时,会先从B1对象中查找名称P()(因为b11的显式类型是B1指针),发现P()是一个虚函数,因此会从对象b11的虚函数表中查找P()的地址。由于b11对应的实际类型C1并没有重载P(),因此内存中b11对象的虚函数表中P()的指针仍然是B1::P(),并没有被覆写。接着查找在B1::P()中看到了名字print(),并继续查找print(),且查找过程同上面的分析一致,所以最终调用的也是B1::print()

表达式5看到P()时会先到类B2的作用域里面查找,发现找不到,因此就会扩大查找范围,到B2类的基类B1中查找,结果找到了。然后的分析过程就跟上面一样了,最终也是调用的B1::print()
如果

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/627662
推荐阅读
相关标签
  

闽ICP备14008679号