Inheritance and multiple files in C++
I have multiple classes that inherit from one base class, and each class is in a separate header. I want the user to be able to include just the base class header, but that would require me to include the other derived classes in the base header, which would lead to some sort of circular dependency, and I've read somewhere that circular dependency is a bad thing.
My class is a socket class, and the derived classes are socket_udp, socket_tcp, socket_raw, and so on.
开发者_运维技巧How do I solve the circular dependency? Maybe the class design is bad, and I don't need different classes for different socket types? I'm a bit confused here.
Thanks!
One option would be to create a new header file that includes all of the header files for the derived and base objects. Just including that single header would therefore include all the other header files. If you order the includes in this file so that you never include a class without first including all its parent classes, you can avoid circular dependencies.
One could add #include
directives to the bottom of the base class header, to force inclusion of the derived classes after the base class is defined.
Then the derived class headers won't need to #include
the base class header, breaking the loop.
It sounds like you are trying to create a system where the implementation of the socket (raw,udp,tcp) is totatly hidden from the end-user -- I assume that is why you don't want the other header files to be included.
One option is to just have all the methods in your socket to be pure virtual, and then have each implementation compile as its own unit, returning just a reference to the base class. However you will still have to provide a factory interface so that the socket can be instantiated to the right type;
So something, like;
socket.h:
class socket {
public:
virtual void send(std::string& data) = 0;
....
};
socket& factory_socket_tcp(some parameters);
socket& factory_socket_udp(some parameters);
socket_tcp.cpp:
class socket_tcp :public socket {
public:
virtual void send(std::string& data);
....
};
socket& factory_socket_tcp(some parameters) {
socket &s = socket_tcp(....);
return s;
}
Or you can go the alternative route of a pImpl (aka Opaque Pointer) as described in this answer here -- The Opaque Pointer have the benefit of having all of the implementation details hidden inside the cpp file, so nothing is leaked out to the .h file. For true public interfaces this is usually the preferred option
Unless the base class definition contains, for any reason, any information of the derived classes, the base class header file should not include the derived classes' header files. Thus, in reality there is no such circular dependency problem as you have described. If the base class definition does contain some information from the derived classes, then I suppose your class hierarchy layout is really misdesigned.
But I actually believe that you've phrased a problem, and what do you really want to do is a different thing: to create a header file that contains every interesting (derived) class, so that an application can conveniently include only this single header file and have every derived class' declaration available. That is, some sort of summary header file.
And this is exactly the recommended solution to your problem. Avoid messing up the base class header file: just create a separate one that includes every other derived class' header file. This way, you leave the files related to the class hierarchy intact, and also permits that an application includes selectively some or other class declaration without including all of them. Some well known libraries, like Qt, use this approach.
精彩评论