开发者

Nested inheritance trouble in Visual Studio 2008

I am currently working on a widget-based graphical user interface. It is structured as a tree with Widgets as the leaves and Containers as the nodes of the tree. The (solvable) problem with this structure is that the Widget-class takes a reference to the Container that is its parent. However, this makes it impossible for the Container class to access the prote开发者_运维百科cted members of the Widget-class (here the "draw" member is causing trouble).

Here is the core of the code causing the problem. Of course this can be solved by making the members public. However, that is not the style that I would like.

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;
}

And this is the output Visual Studio 2008 gives me when I am trying to compile my code:

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

Any suggestions would be appreciated!

Filip


Your code is essentially equal to this, with regard to your specific problem:

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.
    }
};

The problem is that although Derived inherits from Base, it still doesn't have access to Base's protected members. The way access rights works here is as follows:

  1. Derived can not access Base's protected stuff if Base is a different instance.
  2. Derived can access Base's protected stuff in it's own instance.
  3. Derived can access another Derived's private stuff.

The quickest way to solve your problem would probably make Container::draw() a friend of Widget.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜