【问题标题】:How is my method call resolved?我的方法调用如何解决?
【发布时间】:2012-03-12 20:24:11
【问题描述】:

明确说明以下案例中的方法解析规则是什么。我有一个想法,基于代码的行为,但想澄清一下。

基于“调用对象的 const-ness 确定哪个版本的 MyArray::Get() 将被调用,因此是否给调用者一个引用,他可以使用该引用来操作或仅观察其中的私有数据对象。这两种方法在技术上具有不同的签名,因为它们的“this”指针具有不同的类型,允许编译器从wikipedia const correctness 中选择正确的“,我会得出结论,我的示例应该是 方法重载的情况, not 方法覆盖(因为 const 方法和非 const 方法有两个不同的签名)。

class Base
{
public:

    void test()
    { std::cout << "nonconst call" << std::endl; }
};

class Child : public Base
{
public:

    void test() const
    {
        std::cout << "const call" << std::endl;
        Child * nonConstThis = const_cast<Child * >(this);
        Base * nonConstBase = dynamic_cast<Base * >(nonConstThis);

        // This call leads to infinite recursion by calling
        // "void Child::test() const", which implies that
        // a "Child *" will resolve to calling a const Child function
        // before calling a non-const Base function.
        //nonConstThis->test();

        // This will call "void Base::test()"
        nonConstBase->test();
    }

};

void main()
{
    Child * child = new Child;
    child->test();
}

【问题讨论】:

    标签: c++ overriding constants overloading method-signature


    【解决方案1】:

    实际上是方法隐藏,而不是重载。

    在派生类中创建同名方法时,基类版本不再可见。

    struct A
    {
        void foo() {}
    };
    
    struct B : public A
    {
        void foo(int x) {}
    };
    
    B b;
    b.foo(); //error
    

    我假设您希望 B::foo() 存在,但正如您所见,它不存在。所以没有什么,不是 cv-qualifiers (const) 或参数会影响这一点。

    在您的情况下,名称未解析,因为它与 const 有关,而是因为您在 Child 类型的对象上调用 test。然后,您可以在 Base 类型的对象上调用 Base::test(),就像下面的示例一样:

    ((A)b).foo();
    

    【讨论】:

    • 对。 Child 中的 const 版本隐藏了 Base 中的非 const 版本,并防止它成为过载。
    【解决方案2】:

    您对重载名称解析在 C++ 中的工作方式感到困惑。基类中的函数“test”变为“隐藏”(称为名称隐藏)。在寻找合适的函数来调用时,编译器首先在派生类中查找,找到匹配项,然后停止查找。 This answer has a good description as to why.

    您也可以使用 using 声明来查看基类,如下所示:

    class Child : public Base
    {
    public:
        using Base::test;
    

    这将告诉编译器也在 Base 中进行测试。

    【讨论】:

    • 据我所知,没有问题需要解决。
    • @zdan 这澄清了一些事情。另外,我刚刚确认了将 Base 设为虚拟会使 Base::test() 暴露。
    猜你喜欢
    • 2012-05-29
    • 2012-08-31
    • 2018-06-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-26
    • 1970-01-01
    • 1970-01-01
    • 2020-05-06
    相关资源
    最近更新 更多