【问题标题】:Inheritance and pointers to protected members继承和指向受保护成员的指针
【发布时间】:2016-02-29 20:46:58
【问题描述】:

我目前正在为我正在编写的游戏创建一个基本的 UI 系统。它被组织成一棵节点树。我正在尝试编写它,以便只有根节点可以调用其他节点上的更新方法。我以为我了解 C++ 继承,但它再次嘲笑我的无能。我尝试在下面创建一个简单的示例:

class Base
{
    public:
        virtual ~Base() { }

    protected:
        virtual void update_internal() = 0;
};

class Node_A : public Base
{
    protected:
        virtual void update_internal() { std::cout << "Update Node A" << std::endl; }
};

class Node_B : public Base
{
    protected:
        virtual void update_internal() { std::cout << "Update Node B" << std::endl; }
};

class Root : public Base
{
    public:
        void add_node (Base* node) { m_nodes.push_back(node); }

        void update()
            {
                for (auto& node : m_nodes)
                {
                    node->update_internal();
                }
            }

    protected:
        std::vector<Base*> m_nodes;
        virtual void update_internal() { }
};


int main()
{
    Node_A alpha_node;
    Node_B beta_node;
    Root root_node;

    root_node.add_node(&alpha_node);
    root_node.add_node(&beta_node);

    root_node.update();
}

当我尝试编译这个 GCC 时出现错误:

error: 'virtual void Base::update_internal()' is protected

包括 root 在内的所有节点都从 Base 继承 update_internal() 方法,我不明白为什么它受到保护很重要。我以为只是派生类无法访问的私有成员和方法。

【问题讨论】:

标签: c++ pointers inheritance access-control protected


【解决方案1】:

您只能从派生类的实例调用基类的受保护/私有函数(当然,除非您使用friends)。因此派生类只能访问其基础部分的私有/受保护成员,而不能访问其他基础部分。在您的情况下,您通过引用 Base* in 来调用它

for(auto& node : m_nodes)
     node->update_internal();

所以编译器会抱怨。

【讨论】:

    【解决方案2】:

    只需与 Base 和 Root 成为朋友;

    class Base
    {
        friend class Root; // <- yes,this
        public:
            virtual ~Base() { }
    
        protected:
            virtual void update_internal() = 0;
    };
    

    【讨论】:

      【解决方案3】:

      这是Template Method 模式的股票示例。
      Root 类的公共方法暴露了,需要在内部实现。

      【讨论】:

        【解决方案4】:
        class Base
        {
        protected:
            virtual void update_internal() = 0;
        
            static void DoUpdate( Base *node )
            {
                node->update_internal();
            }
        };
        
        class Root : public Base
        {
        public: 
            void update()
            {
                for (auto node : m_nodes)
                {
                    Base::DoUpdate( node );
                }
            }
        protected:
            virtual void update_internal() override {}
            std::vector<Base*> m_nodes;
        };
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-10-03
          • 1970-01-01
          • 2016-06-12
          • 2014-06-09
          • 2012-04-12
          • 2011-03-04
          相关资源
          最近更新 更多