In C++, I have a certain template function that, on a given condition, calls a template function in another class. The trouble is that the other class requires the full definition of the first class to be implemented, as it creates the second class and stores th开发者_C百科em and manages them in similar fashions.
The trouble is that naturally, they fall as one class, and thus have some tight interop, except that I need them to be two classes for threading reasons. A sort of, master for all threads, one child per thread, system.
Any advice on how this can be implemented?
Edit@comment: I have a problem that looks a little like this:
class Master {
public:
Child* CreateChild() {
return new Child();
}
template<typename T> T* GetSomething(int arg) {
return NULL;
}
};
class Child {
Master* master;
template<typename T> T* GetSomething(int arg) {
if (arg) return master->GetSomething<T>(arg);
else return NULL;
}
};
Those obviously aren't the actual implementations, but similar enough to demonstrate. PIMPL would only help if these were non-template functions, but since they are, then the IMPL needs to be right here.
The Master class manages all the Children (why did I pick Master and Child instead of Parent/Child or Master/Slave?), their memory, lifetimes, etc, and a few other system-wide necessities. But the Child class provides the majority of access and in some cases must fall back to the Master class.
Also, there's no way in hell that I'm going to move to dynamic bindings. The rest of my system already thoroughly abuses dynamic bindings to the absolute max, and I simply can't afford the performance of using them again in this fashion. The Child function in question is called very, very, very often.
For your example, the fact that the classes have a template function makes no real difference; just have a forward reference to the Child class and put the definition of the CreateChild function after the declaration of the Child class:
class Child;
class Master {
public:
Child* CreateChild() ;
template<typename T> T* GetSomething(int arg) {
return NULL;
}
};
class Child {
public:
Master* master;
template<typename T> T* GetSomething(int arg) {
if (arg) return master->GetSomething<T>(arg);
else return NULL;
}
};
Child* Master::CreateChild() {
return new Child();
}
Your best bet is to decouple them as much as possible, and then have the 'child' use only pointers to the 'parent' objects (or vice versa). This might get tricky depending on what you want to do with templates since it requires you to properly separate declarations (header files) from implementations (C files).
Child.h: Don't include Parent.h, instead use a forward declaration (example: class Parent;
). Then you can define functions that take or return parent pointers only (no references or instances). You cannot call any Parent
member functions or access member variables inside the header.
Parent.h: Include Child.h as normal. No restrictions at all on use of Parent or Child objects in this file.
Parent.cpp and Child.cpp: Include Child.h and Parent.h as normal. No restrictions at all on use of Parent or Child objects in these files.
The short answer is: "Move to dynamic bindings."
The long answer. Well, it depends on what exactly you are trying to achieve. But in most cases the PIMPL idiom is usually suitable, but you will have to sacrifice some performance in order to achieve this.
精彩评论