Limiting Scope of #include Directives

2019-05-21 14:32发布

问题:

Let's say I have a header file with a class that uses std::string.

#include <string>

class Foo
{
     std::string Bar;

     public:

     // ...
}

The user of this header file might not want std::string to be included in his/her project. So, how do I limit the inclusion to just the header file?

回答1:

The user of your class must include <string>, otherwise their compiler will not know how big a Foo object is (and if Foo's constructors/destructors are defined inline, then the compiler also won't know what constructor/destructor to call for the string member).

This is indeed an irritating side-effect of the C++ compilation model (basically inherited intact from C). If you want to avoid this sort of thing entirely, you probably want to take a look at the PIMPL idiom.



回答2:

Basically, you don't. Once you've included a file, all of the entities from that file are available for the remainder of the translation unit.

The idiomatic way to hide this sort of dependency is to rely on the pimpl idiom.

That said, why would code using Foo care that <string> was included? All of its entities are in the std namespace (well, except that <string> might include some of the C Standard Library headers, but generally you should code with the expectation that the C Standard Library headers might be included by any of the C++ Standard Library headers).



回答3:

I don't see how this can be done, or if it's possible in c++. The reason being: when the compiler sees the member of type "std::string", it must know what is the type in order to know its size. This information can only be obtained by looking into the class definition in a .h file.

One way the users can use a different string class in their source, is by using "using" construct:

//This is how users can use an adt with same name but in different namespaces

    using std::string;
    string bar = "there";


    using my_own_lib::string;
    string bar1 = "here";


回答4:

You can't do that. If the user doesn't want to include std::string, then he or she should not use that class at all. std::string will have to be included in the project in order to link your class correctly.