Visual Studio 2008中的嵌套继承问题



我目前正在开发一个基于小部件的图形用户界面。它的结构是一个树,widget作为叶子,容器作为树的节点。这种结构的(可解决的)问题是,widget类接受对其父容器的引用。然而,这使得容器类不可能访问widget类的受保护成员(这里的"draw"成员造成了麻烦)。

下面是导致问题的核心代码。当然,这可以通过将成员公开化来解决。然而,那不是我想要的风格。

ClassesTest.h:

class Container;
class Widget {
public:
    Widget(Container *parent);
    virtual ~Widget();
protected:
    Container *parent;
    virtual void draw();
};
class Container : public Widget {
public:
    Container(Container *parent);
    virtual ~Container();
protected:
    std::list<Widget *> childs;
private:
    friend Widget::Widget(Container *);
    friend Widget::~Widget();
    virtual void draw();
    void addChild(Widget *child);
    void removeChild(Widget *child);
};

ClassesTest.cpp

#include "stdafx.h"
#include "ClassesTest.h"
Widget::Widget(Container *parent) {
    this->parent = parent;
    parent->addChild(this);
}
Widget::~Widget() {
    parent->removeChild(this);
}
void Widget::draw() {
    //Draw the leaf
}

Container::Container(Container *parent) : Widget(parent) {}
Container::~Container() {}
void Container::draw() {
    //Draw all the childs
    for (std::list<Widget *>::iterator i = childs.begin(); i != childs.end(); i++) {
        (*i)->draw();
    }
}
void Container::addChild(Widget *child) {
    childs.push_back(child);
}
void Container::removeChild(Widget *child) {
    childs.remove(child);
}

int main(int argc, char* argv[])
{
    //Do something useful!
    return 0;
}

这是Visual Studio 2008给我的输出,当我试图编译我的代码:

1>------ Build started: Project: ClassesTest, Configuration: Debug Win32 ------
1>Compiling...
1>ClassesTest.cpp
1>e:visual studio 2008projectsclassestestclassestestclassestest.cpp(26) : error C2248: 'Widget::draw' : cannot access protected member declared in class 'Widget'
1>        e:visual studio 2008projectsclassestestclassestestclassestest.h(14) : see declaration of 'Widget::draw'
1>        e:visual studio 2008projectsclassestestclassestestclassestest.h(6) : see declaration of 'Widget'
1>Build log was saved at "file://e:Visual Studio 2008ProjectsClassesTestClassesTestDebugBuildLog.htm"
1>ClassesTest - 1 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

任何建议都将非常感谢!

菲利普

你的代码基本上等于这个,关于你的具体问题:

class Base
{
protected:
    virtual void f() {}
};
class Derived : public Base
{
    void h()
    {
        Base().f();    // no can do - Base() creates another instance.
        f();           // sure, why not. it's the same instance, go ahead.
        Derived().f(); // sure, why not. it's the same type, go ahead.
    }
};

问题是,尽管Derived继承了Base,但它仍然不能访问Base的受保护成员。访问权限的工作方式如下:

  1. Derived可以访问Base的受保护的东西,如果Base是不同的实例。
  2. Derived可以在自己的实例中访问Base的受保护内容。
  3. Derived可以访问另一个Derived的私有内容。

解决问题的最快方法可能是让Container::draw()成为Widget的朋友。

最新更新