【发布时间】:2015-10-30 06:14:54
【问题描述】:
我想调用项目中存在的所有对象。我该怎么做?
Class1 Abc;
Class1 Xyz;
Class1 asd[100];
for each (Class1 k in ???)
{
k.dosomething();
}
【问题讨论】:
标签: c++ class for-loop types foreach
我想调用项目中存在的所有对象。我该怎么做?
Class1 Abc;
Class1 Xyz;
Class1 asd[100];
for each (Class1 k in ???)
{
k.dosomething();
}
【问题讨论】:
标签: c++ class for-loop types foreach
C++ 没有“项目”的概念,因此对于如何在项目中给定类的所有对象上调用方法没有正式的正确答案。
你的意思可能是在“程序”中。
一种方法是在一组全局对象指针中注册一个指向每个对象的指针。这样做的一个主要问题是,理想情况下,必须由构造函数完成注册工作,而构造函数不知道该对象是否会以const 结尾。因此,您可能会无意中最终在 const 对象上调用修饰符方法。
一个(有限的)解决方案是在可行的情况下将do_something 用作const 方法。
另一个(一般但更复杂的)解决方案是将该类的对象的创建限制为工厂函数,因为工厂函数可以在构造成功后将其转为const 后注册对象。
【讨论】:
C++ 没有type introspection,所以不可能。
您可以通过将Class1 的所有对象存储在一个容器中来解决它,然后对其进行迭代。例如,您可以有一个静态成员变量、一个向量,并且在构造函数中您只需将this 添加到向量。但它只适用于那个单一的类,并且没有好的或标准的方法来概括它。
有些库可以添加简单的类型自省功能,但它总是需要您向类添加额外的代码,并使用宏。
【讨论】:
vector 对这项任务来说效率很低。
C++ 语言不支持此功能,但您可以将其实现为object pool pattern。这种模式对于在受到严格限制的环境中进行高效的内存管理和经济地使用内存和其他资源特别有用,在这种环境中,即使是很小的性能提升也至关重要。
【讨论】:
您可以使用Curiously recurring template patterns 从一个类继承,该类会为您更新包含所有类的容器。
#include <iostream>
#include <unordered_set>
template <typename T>
class IterableType{
public:
std::unordered_set<T const*>& allClasses(){
return classes_;
}
protected:
IterableType(){
IterableType<T>::classes_.insert(static_cast<T*>(this));
}
IterableType(const IterableType<T>& t){
IterableType<T>::classes_.insert(static_cast<T*>(this));
}
IterableType(const IterableType<T>&& t){
IterableType<T>::classes_.insert(static_cast<T*>(this));
}
IterableType<T>& operator=(const IterableType<T>& t){
return *this;
}
IterableType<T>& operator=(const IterableType<T>&& t){
return *this;
}
~IterableType(){
IterableType<T>::classes_.erase(static_cast<T*>(this));
}
private:
static std::unordered_set<T const*> classes_;
};
template <typename T>
std::unordered_set<T const*> IterableType<T>::classes_;
构造函数和析构函数受到保护,因为它们只能从派生类中调用。由于该集合是用 const 成员声明的,因此它永远不允许修改 const 类。但是,如果您想在迭代时修改它们,则需要使用 const_cast 或从声明中删除 const。但正如所说,这些将允许修改 const 对象。
要使用它,您只需使用子类作为模板参数从此类继承。
class Class1:public IterableType<Class1>{
public:
Class1(int n):n_(n)
{}
void print() const{
std::cout << n_ << std::endl;
}
private:
int n_;
};
int main(){
Class1 a(3),b(7),c(8);
for (auto i:a.allClasses()){
i->print();
}
return 0;
}
编辑:实现了复制和移动构造函数并使集合成为常量
【讨论】: