문제

In C++ and Objective-C, I've gotten into the habit of forward-declaring any necessary classes that do not need to be defined in the header, and then importing the header files defining those classes in source files if needed.

Is there ever a situation in which this wouldn't be a good idea?

(I know the big disadvantage of forward declaration is the limited usability of an incomplete type. For the purpose of this question, assume that in the header I only need to use the forward-declared class as an incomplete type.)

도움이 되었습니까?

해결책

Sometimes you can change the semantics of the program subtly without raising any errors

class Foo;

template < typename T>
struct Trait
{
    static const int MY_TYPE = -1;
};

// Lets say this is Foo.h
//class Foo
//{
//};
//template<>
//struct  Trait<Foo>
//{
//  static const int MY_TYPE = 1;
//};

void TestFunction(Foo& f)
{
    std::cout << Trait<Foo>::MY_TYPE << std::endl;
}

Consider the above code and the commented out code lives in a header. If the header is included TestFunction will print 1 otherwise -1

다른 팁

One disadvantage might be the lack of information hiding / encapsulation.

I prefer to have the most minimal header file I can. It means I'm not obligated to continue supporting so many features. If I want to change something, and that something hasn't been exposed in the public header, there is a much better chance I can change it internally to the class without affecting anyone else.

EDIT:

Luke asked for an example, so here ya go:

Suppose you have a class called Car. And, the only thing you built it for was to get from point A to point B. Me, personally, I'd prefer to keep my header file to: a class called Car, and a method called Drive. From the way you phrased your question ("all the classes that I can") I would expect to find classes like "DieselEngine", "PetrolEngine", "HybidEngine" and such in your header file as well. The problem with this is that other people working on your project (or, you, over time) start to use those exposed classes. Now, two years later, you decide "Hrm... that PetrolEngine class is really causing problems for me. I think I'm just going to remove it and replace it with the HybridEngine entirely in my Car class" - well, now PetrolEngine is encluded in 100 other files for reasons you don't understand - and now you're forced to keep PetrolEngine around (and working as it used to) for all those other guys who used it in some say you're not really sure of - because you didn't have a solid working "contract" for how you wanted that class to be used in the first place. It was an implementation detail of what you really wanted to accomplish - building a car.

EDIT to discuss comments about information hiding:

If all you're doing is strictly forward-declaring the class/struct name - well, I guess I would ask "why" again. If I'm a consumer of your header file and class(es), and I can't actually do anything with that class - and it's not exposed as a parameter or return type of your principal class's API - then why expose it at all?

If you are using it for compile time type safety checks for opaque data structures - fine - that's one thing. But, the way you phrased your question made it sound to me like everything went in the header file as a matter of course.

Forward declarations can be applied to many things: classes, functions, global variables/constants (using extern) and in C++11, enums.

The main disadvantage, as far as I can see, is the redundancy, because redundancy introduces more scope for errors, however this apply very differently depending on what you are forward declaring.

If you have an error with the forward declaration of a class, a global or an enum, the compiler should pick it up (yeah!).

If you have an error with the declaration of a function, then in C++ you've simply created an overload (oups!).

I would therefore say that there is no real disadvantage to forward declaring classes, globals or enums; however when it comes to functions, it's better if you stick to #include, you can always create headers grouping the related functions to avoid creating too many files.

None, as far as I know. The only disadvantage, that you already covered, is about using incomplete types. Since you say that there won't be any usages that need fully defined types, you're fine I guess.

Forward declarations are preferred to full file inclusion if you don't need the whole definition of the class in the header. The only disadvantage I can think of was already posted as a comment by @Stephen Darlington which I would give 10 upvotes if I could. :)

One disadvantage is potential memory leak in forward declared types. See this question for more details. Microsoft compilers issue warning C4150: deletion of pointer to incomplete type 'SomeType'; no destructor called in this case.

It is perhaps mostly a question of readability for your colleagues which will have to continue your coding work.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top