电子 网站模板,厦门海投工程建设有限公司网站,什么推广网站好,零食网站色调搭配怎麽做前言
本文将介绍 C 继承体系下#xff0c;函数缺省参数的绑定和函数访问说明符的绑定。这些奇怪的问题实际上不应在我们的代码中出现#xff0c;但它们能帮助我们理解 C 的动态绑定和静态绑定#xff0c;也能帮助我们更好的通过面试。
缺省参数值
先来看一段代码#xf…前言
本文将介绍 C 继承体系下函数缺省参数的绑定和函数访问说明符的绑定。这些奇怪的问题实际上不应在我们的代码中出现但它们能帮助我们理解 C 的动态绑定和静态绑定也能帮助我们更好的通过面试。
缺省参数值
先来看一段代码
class A {
public:virtual void fun(char ch A) {cout ch endl;}
};class B : public A {
public:virtual void fun(char ch B) {cout ch ch endl;}
};int main() {A* pa new B;pa-fun();return 0;
}上述代码的运行结果是什么是 A 还是 BB 呢
很遗憾都不是代码的运行结果是 AA。
解释
发生这种现象的原因是virtual 函数是动态绑定而缺省参数是静态绑定。静态绑定又名前期绑定在编译时确定动态绑定又名后期绑定在运行时确定。 cppreference 对这行为的解释虚函数的覆盖函数不会从基类定义获得默认实参而在进行虚函数调用时默认实参根据对象的静态类型确定。 静态类型与动态类型
A* pa new B; // 静态类型是 A*动态类型是 B*
B* pb new B; // 静态类型是 B*动态类型是 B*对象的静态类型就是我们在代码中所写的类型而动态类型则是指「目前所指对象的类型」。
这样也就能解释上述代码了因为 a 的静态类型是 A*在编译时参数的缺省值绑定的是 ‘A’。而虚函数是动态绑定取决于动态类型绑定的是 B 类中重写后的函数实现。 为什么 C 采用了如此奇怪的方式运行 答案在于运行期效率。如果缺省参数是动态绑定编译器就必须有某种方法在运行期为 virtual 函数决定适当的参数缺省值。这比目前实行的「在编译期决定」的机制更慢而且更复杂。
访问说明符
下面来看一段更加奇怪的代码
class A {
public:virtual void fun() {cout A endl;}
};class B : public A {
private:virtual void fun() {cout B endl;}
};int main() {A* pa new B;pa-fun();B b;b.fun();return 0;
}上述代码的运行结果是什么
a-fun() 正确并打印出 Bb.fun() 报编译错误无法访问 private 成员。
解释
发生这种现象与访问说明符作用时间有关。 cppreference 对访问说明符的说明 每个类成员静态、非静态、函数、类型等的名字都具有与其关联的「成员访问」。在程序的任何位置使用成员的名字时都会检查其访问而且如果它不满足访问规则那么程序不能编译。成员访问检查是对任何给定语言构造进行解释之后的最后一步。此规则的目的是使得以 public 替换任何 private 时始终不会改变程序的行为。 对虚函数的名字的访问规则在调用点使用用于代表调用该成员函数的对象的表达式的类型进行检查忽略最终覆盖函数的访问。 从上述表述可以得出两点
访问说明符只在编译时有效当代码加载到内存后没有任何访问说明符上的区别虚函数的访问说明符由调用该虚函数的对象的静态类型决定
这也就能解释上述代码了
pa 的静态类型为 A*A::fun() 是 public 的可以调用。b 的静态类型是 BB::fun() 是 private 的不能调用。