C – 通过单个指针访问多个对象的接口
我需要存储一个指向对象的指针容器.
这些对象有一些常见的方法/属性(接口),我想强制执行(可能在编译时)和使用. 例: struct A{ void fly(){} }; struct B{ void fly(){} }; A a; B b; std::vector<some *> objects; objects.push_back(&a); objects.push_back(&b); for(auto & el: objects) el->fly(); 更简单的解决方案是A和B继承一个像FlyingClass这样的公共基类: struct FlyingClass{ void fly(){} }; struct A: public FlyingClass { ... struct B: public FlyingClass { ... 并创建一个 std::vector<FlyingClass *> objects; 这将起作用并且还强制执行这样的事实:我只能添加可以飞行的对象(实现FlyingClass). 但是如果我需要实现一些其他常见的方法/属性而不将它们与上面的基类耦合呢? 例: struct A{ void fly(){} void swim(){} }; struct B{ void fly(){} void swim(){} }; 我想这样做: for(auto & el: objects) { el->fly(); ... el->swim(); ... } 更一般地,我将能够调用一个函数传递其中一个指针并访问常见的方法/属性,如: void dostuff(Element * el){ el->fly(); el->swim(); } 我可以尝试从另一个接口继承,如: struct SwimmingClass{ void swim(){} }; struct A: public FlyingClass,public SwimmingClass { ... struct B: public FlyingClass,public SwimmingClass { ... 但那么容器应该包含什么? std::vector<FlyingClass&&SwimmingClass *> objects; 当然,我可以实现SwimmingFlyingClass,但如果我需要RunningClass等,那将会是一场噩梦. 或者有一些重新思考问题的模板方法? 解决方法
有可能以一种漂亮的TMP方式执行此操作,这在运行时有点贵.重新设计是有利的,因此不需要这样做.长期和短期是,如果没有C语言提供的语言支持,您想要做的事情是不可能的.
至于丑陋,请保护你的眼睛: struct AnyBase { virtual ~AnyBase() {} }; // All derived classes inherit from. template<typename... T> class Limited { AnyBase* object; template<typename U> Limited(U* p) { static_assert(all<is_base_of<T,U>...>::value,"Must derive from all of the interfaces."); object = p; } template<typename U> U* get() { static_assert(any<is_same<U,T>...>::value,"U must be one of the interfaces."); return dynamic_cast<U*>(object); } } 其中一些东西没有被定义为标准,所以我将完成它.构造函数上的static_assert强制U从T的所有T继承.我可能有U和T错误的方式,并且all的定义留给读者. getter只需要U是模板参数T之一….然后我们事先知道dynamic_cast会成功,因为我们静态地检查了约束. 这很难看,但应该有用.考虑一下 std::vector<Limited<Flying,Swimming>> objects; for(auto&& obj : objects) { obj.get<Flying>()->fly(); obj.get<Swimming>()->swim(); } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |