为什么这段代码不能编译?

时间:2013-08-22 17:48:24

标签: c++ class gcc compiler-errors

我遇到这样的情况:

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 个答案:

答案 0 :(得分: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)); }

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

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

此功能允许您使用派生类的基类的带阴影或重写成员:

struct X
{
    void Foo();
};

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

但这确实意味着,如果您的意思是Xstruct X一样,则需要使用其全名对其进行限定,并将其命名为::X

答案 3 :(得分:-1)

当您使用私有继承从Bar继承Foo时,您将所有Foo的成员数据/函数设为私有。因此,当您从Fooey继承Bar时,它无法访问任何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)); }
};

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