Visual Studio 2008 中的嵌套继承问题

发布于 2024-12-07 17:25:16 字数 2418 浏览 2 评论 0原文

我目前正在开发基于小部件的图形用户界面。它的结构是一棵树,以 Widgets 作为叶子,以 Containers 作为树的节点。此结构的(可解决的)问题是 Widget 类获取对其父级 Container 的引用。然而,这使得 Container 类无法访问 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 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 ==========

任何建议将不胜感激!

菲利普

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 protected 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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

最好是你 2024-12-14 17:25:16

对于您的具体问题,您的代码本质上与此相同:

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. 如果 Base 是,Derived不能访问 Base 的受保护内容另一个例子。
  2. Derived 可以在其自己的实例中访问 Base 受保护的内容。
  3. Derived 可以访问另一个 Derived 的私有内容。

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文