c++中的继承和多文件

Inheritance and multiple files in C++

本文关键字:文件 继承 c++      更新时间:2023-10-16

我有多个继承自一个基类的类,每个类都在一个单独的头文件中。我希望用户能够只包含基类头文件,但这需要我在基类头文件中包含其他派生类,这会导致某种循环依赖,我在某处读到过循环依赖是一件坏事。

我的类是套接字类,派生类有socket_udp、socket_tcp、socket_raw等。

如何解决循环依赖?也许类设计很糟糕,我不需要针对不同的套接字类型使用不同的类?我有点糊涂了。

谢谢!

一种选择是创建一个新的头文件,其中包含派生对象和基对象的所有头文件。因此,只包含单个头文件就包含了所有其他头文件。如果你对这个文件中的包含进行排序,这样你就不会在包含一个类之前先包含它的所有父类,你就可以避免循环依赖。

可以将#include指令添加到基类头文件的底部,以便在基类定义后强制包含派生类。

那么派生类头就不需要#include基类头,打破循环

听起来您正在尝试创建一个套接字(raw,udp,tcp)的实现对最终用户完全隐藏的系统—我认为这就是为什么您不希望包含其他头文件的原因。

一种选择是让套接字中的所有方法都是纯虚的,然后让每个实现作为自己的单元编译,只返回对基类的引用。但是,您仍然需要提供一个工厂接口,以便将套接字实例化为正确的类型;

比如;

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;
    }

或者你可以选择pImpl(又名不透明指针)的替代路线,如这里的答案所述——不透明指针的好处是将所有的实现细节隐藏在cpp文件中,因此没有任何内容泄露到.h文件中。对于真正的公共接口,这通常是首选选项

除非基类定义出于任何原因包含了派生类的任何信息,否则基类头文件不应该包含派生类的头文件。因此,实际上不存在您所描述的这种循环依赖问题。如果基类定义确实包含来自派生类的一些信息,那么我认为您的类层次结构布局确实设计错误。

但我实际上相信你已经提出了一个问题,你真正想做的是一个不同的事情:创建一个包含每个有趣的(派生)类的头文件,这样一个应用程序可以方便地只包含这个头文件,并有每个派生类的声明可用。也就是说,某种形式的摘要头文件。

这正是建议解决你的问题的方法。避免弄乱基类头文件:只需创建一个单独的头文件,其中包括所有其他派生类的头文件。这样,您就保留了与类层次结构相关的文件,并且还允许应用程序选择性地包含某些或其他类声明,而不包括所有类声明。一些著名的库,如Qt,使用这种方法。