Classes vs. #includes

I recently discovered that bad form has #include in your header files, because anyone who uses your code gets all these extra components that they don't necessarily want.

However, for classes that have member variables defined as a type of another class, what is the alternative?

For example, I did things as follows for the longest time:

 /* Header file for class myGrades */ #include <vector> //bad #include "classResult.h" //bad class myGrades { vector<classResult> grades; int average; int bestScore; } 

(Please excuse this is a very artificial example)

So, if I want to get rid of #include lines, is there a way to save vector or do I need to approach programming my code in a completely different way?

+4
source share
7 answers

If your class directly includes an element of data of this type (and not, by the way, a pointer to this type or a reference to this type), then you should have a class declaration accessible so that the compiler knows how many bytes an instance of your object occupies . This usually means that you #include header files.

However, there are methods known as compiler firewalls that can allow you to structure classes in such a way as to give the class access to objects of the appropriate type without including them directly. One of them is pImpl idiom , in which your class implementation looks like this:

 class MyClass { public: /* ... */ private: struct Impl; Impl* pImpl; }; 

Here you forward the struct Impl containing your class implementation, and then store the pointer to the Impl structure in the class. Since having a pointer in your class does not require the size of the object that it points to in order to be known, this is completely normal. Then in the .cpp file you can define an Impl struct:

 struct MyClass::Impl { /* ... */ }; 

and you can implement all the member functions of the class simply by following the pImpl pointer to the actual fields. This has the disadvantage that all window access requests require a pointer, but the ability to quickly change the implementation of the class makes this useful.

Another option along the same lines is to make the class an abstract base class, and then provide a static factor function that returns an object that subclasses your base class, which actually contains the implementation. For instance:

 class MyClass { public: virtual ~MyClass(); /* Need virtual dtors in polymorphic classes! */ virtual void doSomething() = 0; /* ... etc. ... */ static MyClass* New(/* ... args ... */); }; 

Then, in the .cpp file, you can define a specific subclass of MyClass that actually does all the work:

 class ActualClass: public MyClass { public: void doSomething(); /* ... etc. ... */ private: /* ... data members ... */ } 

and finally, implement New to create a new instance of the implementation class:

 MyClass* MyClass::New(/* ... args ... */) { return new ActualClass(/* ... args ... */); } 

Hope this helps!

+3
source

There is absolutely nothing wrong with including other headings.

You must be sure that your heading contains all the headings on which it depends, and you should avoid including extraneous unwanted headings.

+2
source

Bad form: # includes your header files

I do not think you can say that with such certainty. If you have a function in the header file that accepts std :: vector, you really cannot avoid including this header file.

You are correct that there should not be UNNECESSARY in your header files. If you need something for your implementation that does not need to be expanded in your header file, save it in your implementation.

But I would not go out of my way to not include things in your headlines.

+2
source

I recently discovered that this is a bad form that includes #include in your header files, because anyone who uses your code gets all these extra features that they don’t necessarily want.

... and, as you will now find out, it's not as great as it sounds. It is always useful to reduce your dependencies, and if you can use the name without knowing what it looks like, then forward declarations are better ... but the one who told you that this is a bad form includes simply FOS in your title.

That those who use your WANT code are completely incompatible. If they are going to use your class, then they NEED to use all the definitions for the objects on which your class depends directly (and not just on the name dependencies). If you use a member variable of type WTF, then someone just needs to include the header for WTF in order to use your class, and it must be included before the definition of your class. Much better, MUCH, MUCH is better to include such headers yourself, so that your class clients do not have to determine where the FTS WTF is defined, and enable it before including your class header.

In other words, do exactly OPPOSITE of what you were told. A GOOD form includes all the headers needed to declare your class.

+1
source

Edited: I do not agree that including headers is bad. If necessary, it is necessary. If you redirect a class declaration, you do not need to include a header file, however this can be used if your member variables are pointers or references.

I use forward declaration whenever possible. However, I would not change the class member to avoid including the header file, since I see nothing wrong with that.

0
source

It seems that not everyone agrees with reducing heading dependencies, but I definitely do. As the size of the projects increases, excessive addition significantly increases the assembly time of individual compilation units and means that when you change, you must rebuild more code.

It is often useful to have one header file that contains only the minimum minimum amount for the compiler to know the size of the object, and the other - any built-in function definitions. sizeof (vector) is usually 2 * sizeof (classResult *), it does not depend on what is in the Result class, so in the initial example you only need to forward declare classResult.

C ++ has an annoying quirk where a structure should be declared as a struct and a class should be declared as a class, even though the two are really the same, besides whether the default members are public or private. However, in general, forward declarations can be used as much as possible, as they can greatly reduce header file dependencies.

The pimpl idiom mentioned above can also be useful, but requires some caution as to when and where it is used, as it can hurt performance at runtime, requiring additional indirectness. If the object is created only on the heap, you can make ctor private and use the public static factory method instead. Implementations of this function can then apply this to a real type, for example.

 // In header file class Foo { public: static Foo * Create(); void DoSomething(); private: Foo(); Foo( const Foo & ); Foo & operator=( const Foo & ); }; // In c++ file struct FooImplementation { int bar; }; Foo * Foo::Create() { return (Foo*) new FooImplementation; } #include <stdio.h> void Foo::DoSomething() { FooImplementation * const self = (FooImplementation*) this; printf( "bar = %i", self->bar ); } 

The main problems with this approach are that sizeof (Foo) does not give the correct value (hence the Create () function) and that it is a hack. Personally, I feel that increasing the performance of shorter compilation times makes this a hack for a while.

0
source

Wow, so I'm totally wrong. Riviera approached him with her comment.

My source was around 7:30 in - http://channel9.msdn.com/shows/Going+Deep/C9-Lectures-Stephan-T-Lavavej-Standard-Template-Library-STL-3-of-n/

However, returning to this, he meant the "use" of directives. I must have listened to her, listening to him.

Interesting answers, however, especially templatetypedef. Thanks guys (and apologies for the trouble)

0
source

Source: https://habr.com/ru/post/1337628/


All Articles