C++ collection class to call children functions
The project I'm working on has some pretty nasty collection classes that I feel could use a redesign. I'd really like to make a collection template class that takes model instances and provides a way to call type-specific functions of each child in the collection. For example, something like:
MyCollection<Student> BiologyStudents();
// [Fill the collection]
BiologyStudents.EnrollInClass(ClassList::Biology);
BiologyStudents.Commit();
The idea is that I could easily enroll all students in a class using my collection, then commit those changes to a database. My problem is in how to expose that EnrollInClass()
function which belongs to the children Student objects? If my collection contains objects of a different type than Student, I would like those functions to be exposed from the collection. The only way I can think to do that with my semi-limited C++ knowledge would be to make a f开发者_C百科unction that takes a parameter which references a function I know is in the containing child class. This wouldn't provide compilation errors if you call the wrong function or provide the wrong parameters, so I'd like a way to utilize the compiler to provide these checks.
Is this possible? If so, how? As a warning, I'm used to generic programming in Java/C#, so my impression of C++ templates might be a bit off.
One way would be to use a method pointer:
template <typename T>
struct MyCollection {
template <typename U>
void ForEach(void (T::*func)(U),U param)
{
// for each item loop goes here
(item.*func)(param);
}
};
MyCollection<Student> BiologyStudents;
// [Fill the collection]
BiologyStudents.ForEach(&Student::EnrollInClass,ClassList::Biology);
You would have to provide different versions for different numbers of parameters.
With C++11, you can do this:
template <typename T>
struct MyCollection {
void ForEach(std::function<void (T &)> func)
{
// for each item loop goes here
func(item);
}
};
MyCollection<Student> BiologyStudents;
// [Fill the collection]
BiologyStudents.ForEach([](Student &s){s.EnrollInClass(ClassList::Biology);});
Which would not require making different versions of ForEach for different numbers of parameters.
精彩评论