从内部类访问外部类,而无需显式传递实例

时间:2019-07-27 18:31:47

标签: c++ c++11 inner-classes

以下代码产生输出

outer::inner::inner, o=00000000
outer
outer::inner::val, o=00000000
outer::print

有人能解释我如何通过print访问外部类方法o而不在构造时显式分配o的值吗?

此处o为空,但是我仍然可以调用其方法。

我已经使用MSVC 2017和g ++ 7.4.0对此进行了测试,并且输出是相同的。

#include <iostream>

class outer {
public:
    outer() { 
        std::cout << __func__ << std::endl; 
    }

    class inner {
        outer *o = nullptr;
    public:
        inner() { 
            std::cout << __FUNCTION__ << ", o=" << o << std::endl;
        }
        void val() { 
            std::cout << __FUNCTION__ << ", o=" << o << std::endl;
            o->print(); // **call outer class method**
        }
    };

    inner i;

    void print() { 
        std::cout << __FUNCTION__ << std::endl;
    }
};

int main()
{
    outer o;
    o.i.val();

    return 0;
}

1 个答案:

答案 0 :(得分:2)

您可以将示例简化为

struct S
{
    void f() { std::cout << "hello world\n"; }
};

int main()
{
    S* s = nullptr;
    s->f();
}

nullptr取消引用是UB。因此,任何事情都可能发生。

为什么显示可以正常工作?

因为在实践中,通常将方法函数实现为好像带有附加参数的常规函数​​一样:

void S::f()-> void f(S*)(或void f(S&)

因此,代码变为:

void f(S* /*unused*/) { std::cout << "hello world\n"; }

int main()
{
    S* unused = nullptr;
    f(unused);
}

在这种情况下,编译器将使用有效代码转换UB,因为未使用unused,它不会崩溃,并且不会执行您期望的操作。