3

我遇到了这样的情况:

struct Foo
{
    void Barry() { }
};

struct Bar : private Foo
{
    template <class F> void Bleh(F Func) { Func(); }
};

struct Fooey : public Bar
{
    void Blah() { Foo f; Bar::Bleh(std::bind(&Foo::Barry, &f)); }
};

而且它不能编译(g++ 4.7.3)。有错误:

test.cpp: In member function ‘void Fooey::Blah()’:
test.cpp:4:1: error: ‘struct Foo Foo::Foo’ is inaccessible
test.cpp:15:23: error: within this context
test.cpp:4:1: error: ‘struct Foo Foo::Foo’ is inaccessible
test.cpp:15:47: error: within this context

但是,如果我这样做:

class Fooey;
void DoStuff(Fooey* pThis);

struct Fooey : public Bar
{
    void Blah() { DoStuff(this); }
};

void DoStuff(Fooey* pThis)
{
    Foo f;
    pThis->Bleh(std::bind(&Foo::Barry, &f));
}

它编译得很好。这背后的逻辑是什么?

4

4 回答 4

7

这里

struct Fooey : public Bar
{
    void Blah() { Foo f; Bar::Bleh(std::bind(&Foo::Barry, &f)); }
};

名称查找查找无法Foo访问的基类,Bar因为它是Bar私有继承的。

要修复它,请完全限定名称:

    void Blah() { ::Foo f; Bar::Bleh(std::bind(&::Foo::Barry, &f)); }
于 2013-08-22T18:01:01.780 回答
1

问题是,内部Foo或任何从它派生的类,Foo注入的类名;一个范围为 inside 的名称Foo,它隐藏了封闭命名空间中类的相同名称。在这种情况下,由于私有继承,这是不可访问的。

您可以通过显式引用命名空间中的名称来解决此问题,在本例中为::Foo. 不幸的是,如果您将类移动到另一个命名空间,这将中断。

于 2013-08-22T18:05:19.397 回答
0

这是名称冲突。对于每个继承的类型,您都会在自己的类中获得该名称的成员。要访问实际类型,您需要通过其限定名称(在本例中为::Foo)来引用它。

此功能允许您使用派生类中基类的隐藏或覆盖成员:

struct X
{
    void Foo();
};

struct Y : public X
{
    void Foo()
    {
        X::Foo(); // calls X's implementation of Foo
    }
};

但这确实意味着,如果您的意思X是 in struct X,则需要用它的全名来限定它,称它为::X

于 2013-08-22T18:01:13.007 回答
-1

当您BarFoo私有继承继承时,您将所有Foo成员数据/函数设为私有。因此,当您从 继承FooeyBar,它无法访问任何Foo成员。

有关私有继承的更多详细信息:http: //www.parashift.com/c++-faq/access-rules-with-priv-inherit.html

struct Fooey : public Bar
{
    void Blah() { Foo f; Bar::Bleh(std::bind(&::Foo::Barry, &f)); }
};

这个包含“修复”范围的块也创建了另一个Foo(也就是说,Fooey 通过它的继承已经有了一个Foo对象Bar- 这是创建另一个并绑定它的Barry)。

于 2013-08-22T18:01:27.883 回答