2015-11-26 3 views
3

В настоящее время я создаю базовую систему пользовательского интерфейса для игры, которую я пишу. Он организован как дерево узлов. Я пытаюсь написать его так, чтобы только корневой узел мог вызвать метод обновления на других узлах. Я думал, что понял наследование 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 

Всем узлы, включая корневой унаследовать update_internal() метод из базы, я не понимаю, почему важно, чтобы он был защищен. Я думал, что доступ к этим классам не возможен только из частных членов и методов.

+2

http://stackoverflow.com/questions/11631777/accessing-a-protected-member-of-a-base-class-in-another-subclass – Amadeus

ответ

4

Вы можете вызвать только защищенную/закрытую функцию базового класса только из экземпляра производного класса (если, конечно, вы не используете friend s). Таким образом, производный класс может получить доступ только к частным/защищенным членам своей базовой части, а не к какой-либо другой базе. В вашем случае, вы называете это через ссылку на Base* в

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

поэтому компилятор жалуется.

2

Просто подружитесь с базой и корнем;

class Base 
{ 
    friend class Root; // <- yes,this 
    public: 
     virtual ~Base() { } 

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

Это пример запаса для шаблона Template Method.
Открытый метод класса Root раскрывает, что необходимо реализовать внутри страны.

1
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; 
}; 
Смежные вопросы