为什么编译器不检查被覆盖函数的存储类?


#include <iostream>
class A{
public:
void printit(register int b) {
std::cout<<"inside A";
}
};
class C:public A{
public:
void printit(int b) {
std::cout<<"inside C";
}
};
int main() {
C c;
c.printit(1);
return 0;
}

在上面的代码中,printit 是 C 中没有存储类寄存器的重写方法。但是,编译器仍然匹配这一点,代码打印"在 C 内部"。为什么寄存器int与int匹配?

C++存储类从未参与过载解析。这是出于显而易见的原因:存储类修改特定变量内存的来源方式/位置。重载解析与用于调用函数的表达式的性质有关。表达式实际上没有存储类。

是的,表示具有存储类的变量的表达式可以说具有存储类。但是表达式也可以是对变量的各种计算。或文字。或函数返回值。这些东西都没有存储类。

因此,虽然您可以声明参数使用register存储类(在某种程度上,register仍然是C++的事情。C++11 弃用了关键字的这种使用,C++17 及更高版本正式删除了它(,这并不意味着它参与重载解决。它只影响所讨论的参数变量获取其内存的方式(当然,在某种程度上,register在C++中根本没有任何行为(。

除此之外,如果从基类继承并创建与基类方法同名的方法,则基类方法将隐藏,除非您使用using声明将它们恢复。因此,即使存储类以某种方式参与了重载解析,您的代码仍然不起作用。

对象是C类型,它会调用类C中的方法,它不知道基类中存在另一个方法。事实上,它不知道基类的存在。

关于在其中一个参数中使用register的重载,它不会区分参数,因为它不是一种类型,它是一个关键字,用于将变量存储在处理器寄存器而不是"正常"内存中。

检查这一点的一种更简单的方法是尝试在同一类中重载:

class A {
public:
void printit(int b);
void printit(register int b);
};

您将遇到编译错误:

'void A::printit(int)' cannot be overloaded with 'void A::printit(int)'

请注意,ISO C++17 删除了存储说明符register

最新更新