作用域,函数解析,调用,虚函数本质

每一个块都是一个作用域(块就是{}中间的)。

同样,每个类也是一个作用域。我们在这个作用域内定义函数和一些数据成员。对于类的派生类而言,它的作用域实际上是嵌套在基类中的。如图所示:


在你调用一个函数或者数据项的时候,它会首先在这个作用于内部去寻找,如果找不到便会在外部作用域去寻找,直到找到为止,如果实在没法找到,那么便会报错。

先举一个类似于类的栗子,如代码所示:

#include<iostream>
using namespace std;
int f1()
{
	return 1;
}
int main()
{
	
	int tmp = f1();
	system("pause");
	return 0;
}

这个程序是正确的main函数内部没有找到,去了全局作用域去找,找到了f1,在进行类型安全检查。大家注意看下面这个例子.

#include<iostream>
using namespace std;
int f1()
{
	return 1;
}
int main()
{
	char f1;
	int tmp = f1();
	system("pause");
	return 0;
}
比较之前的例子,这里多了一个
char f1;

编译器报错,提示为: error C2064: 项不会计算为接受 0 个参数的函数。它竟然匹配到了char f1 上,并没有去匹配函数f1,这意味着编译器如果在当前作用域找到了该名字解析,那么它便不会再去寻找了。

类同样也适用这个规则:

1.派生类作用域嵌套在基类中,所以通过基类的静态类型是无法搜寻到派生类独有的一部分。

2.派生类作用域嵌套在基类中,所以派生类内部如果找不到该成员定义,那么它会去基类那个作用域内部去寻找。

举个栗子:

#include<iostream>
using namespace std;
class Base
{
public:
	void f1() {
		cout << "base's f1() has been called." << endl;
	}
};
class Derive:public Base
{
public:
	void f1(int) {
		cout << "derive's f1(int) has been called." << endl;
	}
};
int main()
{
	Base b;
	Derive d;
	b.f1();   //True 调用基类
	d.f1(0);   //True 调用派生类
	d.f1();   //False 解析错误
	system("pause");
	return 0;
}

最后的解析错误也是上面的原因。此时在派生类声明可以加一个

using Base::f1;

或者调用时加

d.Base::f1();

都可以解决这个问题。

虚函数为什么强制要求必须参数列表和const属性和返回值类型必须相同(除了特例,如返回值是基类引用或指针),如果你参数有差异的话,那么就不会实现多态性,因为派生类的参数不同,所以无法匹配.


猜你喜欢

转载自blog.csdn.net/qq_41657315/article/details/80938189