更新类变量或从成员变量调用类函数会给出运行时错误

时间:2018-02-23 09:58:01

标签: c++ oop c++11

我正在尝试实现更新,它将更新到所有listerner类 我正在使用类变量来计算侦听器的数量。 MyClass 正在扩展监听器,以便从更新程序类进行监听

当我尝试使用成员函数中的类函数更新类变量时,我收到运行时错误。请参考下面的代码,帮助我解决这个问题

 #define MAX_LISTNERS 10
class Listner{
public: 
virtual void onUpdate() = 0;
};
class Updater {
    Listner* ptrListner[MAX_LISTNERS];
    static int count;
    public: 
     static void updateCount(){
        count++;
    }
    void registerListner(Listner* ptrListner){
        this->ptrListner[count] = ptrListner;
        this->updateCount(); //---> Runtime Error
    }
    void updateToListner(){
        for(int i=0;i<=count;i++){
        this->ptrListner[i]->onUpdate();
        }
    }
};
 int  Updater::count = 0;
class MyClass: public Listner{
    public:
     void onUpdate(){
        cout<<"update from MyClass";
     }
};  
class MyClass2: public Listner{
    public:
     void onUpdate(){
        cout<<"update from MyClass2";
     }};
int main() {
    MyClass* obj = new MyClass();
    MyClass2* obj2 = new MyClass2();
    Updater obj_updater;
    obj_updater.registerListner(dynamic_cast<Listner*>(obj));
    obj_updater.registerListner(dynamic_cast<Listner*>(obj2));
    obj_updater.updateToListner();
}

1 个答案:

答案 0 :(得分:1)

这里要考虑的一些事情,因为这似乎有点不安全,而且不符合现代C ++ 11的方式。

  1. 使用RAII进行分配,即使用unique_ptr而不是显式的新/删除
  2. 使用std :: vector而不是C-Style数组声明。您可以在运行时限制数量。这也为您提供了隐式侦听器计数
  3. 让Updater类负责分配,工厂风格也允许您尊重类型安全
  4. 如下所示:

    class Listner
    {
        public:
            virtual void onUpdate() = 0;
    };
    
    class Updater
    {
        using ListnerPtr = std::unique_ptr<Listner>;
        using Listners   = std::vector<ListnerPtr>;
    
        Listners m_listeners;
    
    public:
        template < typename T >
        bool registerListner()
        {
            static_assert(std::is_base_of<Listner, T>::value, "T must be derived from Listner");
    
            if (m_listeners.size() >= 10)
                return false;
    
            m_listeners.emplace_back(std::make_unique<T>());
            return true;
        }
    
        void updateToListner()
        {
            std::for_each(m_listeners.begin(), m_listeners.end(), [](const Listners::value_type& item)
            {
                item->onUpdate();
            });
        }
    };
    
    class MyClass : public Listner
    {
    public:
        void onUpdate() override
        {
            std::cout << "update from MyClass" << std::endl;
        }
    };
    
    class MyClass2 : public Listner
    {
    public:
        void onUpdate() override
        {
            std::cout << "update from MyClass2" << std::endl;
        }
    };
    
    int main
    {
        Updater obj_updater;
        obj_updater.registerListner<MyClass>();
        obj_updater.registerListner<MyClass2>();
        obj_updater.updateToListner();
        return 0
    }