java - C++ 与 Java 中的名称隐藏

标签 java c++ overloading

<分区>

前几天我学到了一些关于 C++ 的新知识;以下不起作用:

class ParentClass {
public: 
    void someFunction() { printf("ParentClass::someFunction()"); }
};

class ChildClass : public ParentClass {    
public:
    void someFunction(int a) { printf("ChildClass::someFunction(int)"); }
};

int main() {
    ChildClass childClass;
    // This call is a compiler error.  
    // I would expect it to call ParentClass::someFunction()
    childClass.someFunction();
}

然而,在 Java(以及其他语言)中做完全相同的事情正如我所期望的那样:

public class ParentClass {
    public void someFunction() { System.out.println("ParentClass"); }
}

public class ChildClass extends ParentClass {
    public void someFunction(int a) { System.out.println("ChildClass"); }
}

public class Main {
    public static void main(String[] args) {
        ChildClass childClass = new ChildClass();
        // The following prints "ParentClass"
        childClass.someFunction();
    }
}

那么在 C++ 中给出了什么?为什么这会隐藏名称而不是重载它?

最佳答案

如果您要问规则是什么,那么只要在一个范围内发现一个或多个重载,名称查找就会停止,并且不会查看任何更大的范围。因此,在您的情况下,someFunction 的搜索从 ChildClass 的范围开始,找到一个匹配项,然后停止。

只考虑名称,不考虑其用法(例如函数调用中的参数数量)、可访问性或其他任何内容。如果没有一个重载可用,搜索仍然不会继续到其他范围,并且程序格式错误。

如果您问为什么规则是这样的,请考虑最初只有一个函数的情况:

struct Base {};
struct Derived : Base {void f(int);}

有人用不完全匹配的类型调用它

Derived d;
d.f(42.0);  // OK: double converts to int

现在假设某个对 Derived 一无所知的人决定 Base 可以使用另一个函数:

struct Base {
    void f(double);  // Completely unrelated to D::f
};

根据 C++ 规则,该函数将被使用 D::f 的代码忽略,它将继续像以前一样工作。如果新函数被认为是一个重载,它会是一个更好的匹配,并且使用 D::f 的代码会突然改变行为,可能导致很多令人头疼和冗长的调试 session 。

如果要将派生类范围内的所有基类函数都视为重载,则使用声明即可。在你的情况下:

using ParentClass::someFunction;

或者,为了避免上述情况,但代价是一些冗长乏味的措辞,您可以为您想要的特定重载编写转发函数:

void someFunction() {ParentClass::someFunction();}

关于java - C++ 与 Java 中的名称隐藏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28586123/

相关文章:

c++ - Qt Quick ui形式不支持功能

c++ - 运算符和拷贝构造函数的重载

java - strace: `dup2(A, B); close(B)` 有什么意义吗?

java - 在 Windows 机器上安装 Java 8 的情况下在 Java 7 上运行 Glassfish

java - Apache POI - 如何在 Grails 应用程序中提供 excel 文件下载

java - Android检测是否在设计模式下调用了构造函数?

c++ - 在可变参数模板上计算函数

c++ - 使共享指针指向新实例

c++ - 重载 C++ 运算符 >> 这样我就可以读取一个 vector (vector <int> vector;)

c# - 除了可选参数之外,两个方法具有相同的签名