I am trying to understand pre-compiled headers. So I set up the following sample project:
pch.hpp
#include <vector>
pch.cpp
#pragma once
#include "pch.hpp"
Vector.hpp
#pragma once
#include "pch.h"
class Vector {
public:
Vector(const size_t N, const int init);
private:
std::vector<int> m_data;
};
Vector.cpp
#pragma once
#include "pch.hpp"
#include "Vector.hpp"
Vector::Vector(const size_t N, const int init)
: m_data(N, init) { }
Source.cpp
#include "pch.hpp"
#include "Vector.hpp"
int main() {
const Vector v1(3, 5);
}
I did this in VS 2022 by marking pch.hpp as the pre-compiled header file under Project Properties --> C++ --> Pre-Compiled Headers --> Header File with Use (/Yu). And setting pch.cpp as Create (/Yc).
Now, when I remove #include "pch.hpp" in Vector.cpp or Source.cpp, I get this error:
File Vector.cpp
Line 10
Severity Error
Code C1010
Description unexpected end of file while looking for precompiled header.
Did you forget to add '#include "pch.hpp"' to your source?
However, if I disable pre-compiled headers, everything compiles fine. As one would expect.
So, it seems that with pre-compiled headers enabled, I now need to put #include "pch.hpp" into every other source file? Even though #include "Vector.hpp" already includes pch.hpp? Is it possible to avoid having to put #include "pch.hpp" into all my other source files?
I ask, because I have a much larger code base (than the example above), and I thought I could essentially replace all instances of #include <vector> with #include "pch.hpp" and be done. But having to add #include "pch.hpp" to numerous cpp files, requires me to touch a lot of files (and seems counter-intuitive).
Apologies for the possibly naive question, as I am new to pre-compiled headers.
Related
When I compiled this program (from C++ Programming Language 4th edition):
main.cpp
#include <stdafx.h>
#include <iostream>
#include <cmath>
#include "vector.h"
using namespace std;
double sqrt_sum(vector&);
int _tmain(int argc, _TCHAR* argv[])
{
vector v(6);
sqrt_sum(v);
return 0;
}
double sqrt_sum(vector& v)
{
double sum = 0;
for (int i = 0; i != v.size(); ++i)
sum += sqrt(v[i]);
return sum;
}
vector.cpp
#include <stdafx.h>
#include "vector.h"
vector::vector(int s)
:elem{ new double[s] }, sz{ s }
{
}
double& vector::operator[](int i)
{
return elem[i];
}
int vector::size()
{
return sz;
}
vector.h
#include <stdafx.h>
class vector{
public:
vector(int s);
double& operator[](int i);
int size();
private:
double* elem;
int sz;
};
It gave me these errors:
I run it on Microsoft Visual Studio 2013, on Windows 7. How to fix it?
You have to properly understand what is a "stdafx.h", aka precompiled header. Other questions or Wikipedia will answer that. In many cases a precompiled header can be avoided, especially if your project is small and with few dependencies. In your case, as you probably started from a template project, it was used to include Windows.h only for the _TCHAR macro.
Then, precompiled header is usually a per-project file in Visual Studio world, so:
Ensure you have the file "stdafx.h" in your project. If you don't (e.g. you removed it) just create a new temporary project and copy the default one from there;
Change the #include <stdafx.h> to #include "stdafx.h". It is supposed to be a project local file, not to be resolved in include directories.
Secondly: it's inadvisable to include the precompiled header in your own headers, to not clutter namespace of other source that can use your code as a library, so completely remove its inclusion in vector.h.
Just include windows.h instead of stdfax or create a clean project without template.
There are two solutions for it.
Solution number one:
1.Recreate the project. While creating a project ensure that precompiled header is checked(Application settings... *** Do not check empty project)
Solution Number two:
1.Create stdafx.h and stdafx.cpp in your project
2 Right click on project -> properties -> C/C++ -> Precompiled Headers
3.select precompiled header to create(/Yc)
4.Rebuild the solution
Drop me a message if you encounter any issue.
You can fix this problem by adding "$(ProjectDir)" (or wherever the stdafx.h is) to list of directories under Project->Properties->Configuration Properties->C/C++->General->Additional Include Directories.
Add #include "afxwin.h" in your source file. It will solve your issue.
Just running through a Visual Studio Code tutorial and came across a similiar issue.
Replace #include "stdafx.h" with #include "pch.h" which is the updated name for the precompiled headers.
I have a problem with the inclusion of the vector module. It seems to there is a conflit with others modules. Here is the structure :
In the simulation.h :
#pragma once
#ifndef SIMULATION
#define SIMULATION
#include <ostream>
#include <sstream>
#include <string>
#include <algorithm>
#include <cstdlib>
// #include <vector>
#include "File.h"
...
void afficherResultat(std::vector<Client> sortie);
...
#endif
And the File.h file :
#pragma once
#ifndef FILE
#define FILE
#include <vector>
class File {
...
std::vector<Client> l;
...
};
#endif
And I get 108 errors starting with : C4091 warning and C4430, C2065, C4229 errors...
Some people spotlight the order of the inclusions. Any Ideas ?
You are defining a macro for an identifier which is part of the standard library:
#define FILE
(see https://en.cppreference.com/w/cpp/io/c#Types for what FILE is).
Doing so is forbidden and will cause very weird errors.
Instead use names which are as unique as possible as include guards, e.g. INCLUDE_GUARD_FILE_H.
If you have an include guard there is also no need for #pragma once which is a non-standard way of solving the double inclusion problem that the include guard is also supposed to prevent.
Additionally you have not declared Client in File.h. Probably some #include for the header file defining Client is missing.
I'm a bit confused at the moment because I'm planning to include multiple source and header files for the first time in one of my projects.
So I'm wondering if this would be the right approach?
Do I have to include the string header in every source file that uses it directly?
And what about the "stdafx.hpp" header that Visual C++ wants me to include?
Would that be the way to go?
main.cpp
#include "stdafx.hpp"
#include <string> //?
#include <stringLib1.h>
#include <stringLib2.h>
using std::string;
//use a windows.h function here
//use a stringLib1 function here
//use a stringLib2 function here
stringLib1.h
#include "stdafx.hpp"
#include <string>
using std::string;
class uselessClass1
{
public:
string GetStringBack1(string myString);
};
stringLib1.cpp
#include "stdafx.hpp"
string uselessClass1::GetStringBack1(string myString) {
return myString;
}
stringLib2.h
#include "stdafx.hpp"
#include <string>
using std::string;
class uselessClass2
{
public:
string GetStringBack2(string myString);
};
stringLib2.cpp
#include "stdafx.hpp"
string uselessClass2::GetStringBack2(string myString) {
return myString;
}
A good practice is usually to include only what your code uses in every file. That reduces dependencies on other headers and, on large projects, reduce compilation times (and also helps finding out what depends on what)
Use include guards in your header files
Don't import everything by polluting the global namespace, e.g.
using namespace std;
but rather qualify what you intend to use when you need it
You don't need stdafx.h in your project unless you're using precompiled headers. You can control this behavior in the VS project properties (C/C++ -> Precompiled Headers -> Precompiled Header)
The stdafx.h header is needed if precompiled header is enabled in VS. (Read this one)
You only need to include the stdafx.h in your .cpp files as the first include.
Regarding the header and cpp files (which come in pairs), include things necessary for the declaration in the header, and include everything else (necessary for the definition) in the cpp. Also include the corresponding header in its cpp pair too. And use include guards.
myclass.h
#ifndef MYCLASS_H // This is the include guard macro
#define MYCLASS_H
#include <string>
using namespace std;
class MyClass {
private:
string myString;
public:
MyClass(string s) {myString = s;}
string getString(void) {return myString;}
void generate();
}
myclass.cpp
#include <stdafx.h> // VS: Precompiled Header
// Include the header pair
#include "myclass.h" // With this one <string> gets included too
// Other stuff used internally
#include <vector>
#include <iostream>
void MyClass::generate() {
vector<string> myRandomStrings;
...
cout << "Done\n";
}
#endif
Then in main(...), you can just include myclass.h and call generate() function.
The stdafx include should be at the top of every .cpp file and it should NOT be in .h files.
You could put #include < string > in stdafx.h if you don't want to put it in every other file.
I suppose that you must be having your own header files also which might be requiring in other cpp files and header files. Like the one you gave
#include <stringLib1.h>
#include <stringLib2.h>
In my opinion, its better to create one common header file in which you include all the common library header files and your project header file. This file then you can include in all the other cpp files and header file. And it will be better to use header guards also.
So, considering a common header file "includes.h".
#ifndef INCLUDES_H
#define INCLUDES_H
#include <string>
#include <stringLib1.h>
#include <stringLib2.h>
/***Header files***/
#endif //INCLUDES_H
This is now your common header file. This you can include in all your project files.
I have searched for a while on this, but I keep getting answers that do not answer this specific scenario.
I have a class called VisibleGameObject. I am wondering what happens if I put my normal includes in the header (so that other developers can use the same class), and put the same include in my pre compiled header stdafx.h
I don't want developers dependent on my pch.
// VisibleGameObject.h
#pragma once
#include "SFML\Graphics.hpp"
#include <string>
class VisibleGameObject
{
public:
VisibleGameObject();
virtual ~VisibleGameObject();
virtual void Load( std::string filename );
virtual void Draw( sf::RenderWindow & window );
virtual void SetPosition( float x, float y );
private:
sf::Sprite _sprite;
sf::Image _image;
std::string _filename;
bool _isLoaded;
};
Implementaion:
// VisibleGameObject.cpp
#include "stdafx.h"
#include "VisibleGameObject.h"
...
PCH:
// stdafx.h
#pragma once
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
// TODO: reference additional headers your program requires here
#include <SFML/System.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <SFML/Audio.hpp>
When I build my project (after I have compiled once), does #include <SFML/Graphics.hpp> get recompiled every time? Because it is included in the header file of this class. I think what happens is that the pch is included first in the cpp file's translation unit and then #include <SFML/Graphics.hpp> is include guarded so the pch works normally and my include is ignored. In Visual Studio, it is an error to not include the pch first. I just want to confirm this behaviour. Does the pch get used normally and no <SFML/Graphics.hpp> code is recompiled?
If the author of the header has any salt at all, then no, it won't be recompiled.
The PCH includes the full definition, including the #ifndef, #define, #endif include guard logic. During PCH-creation the file will be pulled in, compiled, and the include guard identifier formally defined. In your source that follows any #include "stdax.h" all that precompiled content is slurped in. The source will include the suspect header for compilation. However, the preprocessor will skip all the content once the include guard's #ifndef id is found as defined. Note: It is possible it can be recompiled for a translation unit that specifically has PCH turned off, but I doubt you've done that.
In short, you're doing it correctly, and your assessment is accurate.
I've been teaching myself some OpenGL using SFML for creating windows/handling inputs, etc. My main.cpp started getting a bit unwieldy so I decided to start splitting my code up. I created a 4X_vertex.h and a 4X_vertex.cpp (4X is the name of the project) and moved the relevant functions and structs out of my main and into these files. However, when I compile, I get the error
variable or field "drawVertexArray" declared void
which from my research seems to be just an unhelpful message relating to the next error, which is
vertex was not declared in this scope
Here's my list of includes from my main.cpp:
#include <iostream>
#include <fstream>
#include <string>
#include <SFML/System.hpp>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include "4x_vertex.h"
#include "4x_constants.h"
My 4X_vertex.h:
#ifndef _4X_VERT_H
#define _4X_VERT_H
struct vertex{
GLfloat x,y,z;
GLfloat r,g,b;
};
void drawVertexArray(vertex v[]);
vertex* loadVertexData();
#include "4X_vertex.cpp"
#endif
The part of 4X_vertex.cpp that's giving me the trouble:
using namespace std;
void drawVertexArray(vertex v[]){
... openGL stuff...
}
All of this worked before I started moving it around so I'm assuming there's something weird going on with the includes, or something. All help is greatly appreciated!
Just some pointers. Best practice is to divide your project up into multiple source files. Typically, you would use the word "main" in the file name of the main source file (if applicable). So you might have something like...
main.cpp
feature1.cpp
feature2.cpp
tools.cpp
For your other files, you will typically name them after the class they implement. You will most often have both a .h and a .cpp. Put your declarations in the .h and your definitions in the .cpp had have the .cpp include the .h. That might give you...
main.cpp
feature1.cpp feature1.h
feature2.cpp feature2.h
tools.cpp tools.h
The modules that reference one of your classes includes it's .h as well. So, main.cpp might look like...
#include <iostream>
#include "feature1.h"
#include "feature2.h"
using namespace std;
void main(int argc, char **argv)
{ ...
cout << "Done!\n";
}
And feature1.cpp might be...
#include "feature1.h"
#include "tools.h"
feature1_class::feature1_class() { ... }
void feature1_class::AUsefulFeature(int val) { ... }
//etc.
...where feature1.h declares the class, defined constants, etc. f.g.,
#ifndef FEATURE1
#define FEATURE1
#include "tools.h"
class feature1_class
{
public:
feature1_class();
void AUsefulFeature(int val);
int APublicMember;
};
#endif
You may have noticed that tools.h is actually include twice in feature1.cpp. It is included from within the feature1.h and explicitly from the .cpp file. If you use the following pattern in your .h files ...
#ifndef TOOLS_H
#define TOOLS_H
//... do your thing
#endif
... then multiple includes shouldn't cause you any problems. And as you refactor code, it is one less thing to have to worry about cleaning up.
If you have been using a single file for all your source up till now, you may have been compiling like so...
cl main.cpp
Which gives you your .exe and .obj and maybe other files. But with multiple source files involved, it isnt much different. You can say...
cl main.cpp feature1.cpp feature2.cpp tools.cpp
There is much more to learn, but this is a start and helps you on the way to better organization of your coding thoughts.
You need to #include "4X_vertex.h" at the top of your 4X_vertex.cpp file. This will allow the .cpp file to see the declaration for the struct vertex.
In general, each file (both .h and .cpp files) needs to #include any header files which contain declarations for items used in that file. This includes the standard headers and OpenGL headers, as well as your custom ones.