C++Builder11: How to unit test with googletest? - unit-testing
Until recently I've used C++Builder 10.2 for a project, and I had begun to use DUnitX to add some unit tests for the project.
Now I have upgraded to C++Builder 11.2, and found that DunitX is no longer supported for C++Builder when using this version. Instead, Embarcadero recommends to use DUnit or Googletest.
On further research, it seems that Googletest cannot be used with the classic compiler (but I'm not actually interested in using the pre-C++11 classic compiler), but also that DUnit cannot be used when targeting the Firemonkey framework, and that DUnit (1) is unmaintained and (2) does not work well with the Clang-based compiler.
I'm interested in using googletest because I have already used both, googletest and googlemock, on less niche platforms than C++Builder such as Linux/GCC, Apple/Clang and Windows/MinGW-w64. I am aware that the googletest project itself refuses to accept build files or patches for C++Builder because they do not want to spend effort to support niche compilers (see e.g. here, here, and here).
I'm happy to learn that some patched version of googletest is currently available for C++Builder through the GetIt package manager, even though it is not clear who has actually made that patch, and although I realize that Embarcadero may remove googletest from the GetIt package manager an any moment.
I've found two blog posts explaining how to install googletest in C++Builder and how to use it, however, I cannot successfully follow the second blog post when it comes to point 6, which reads
In your project group create a new windows64 bit VCL console application. Set this to use the debug settings (this allows you to debug code that doesn’t pass a unit test).As well as the files you want to test and the files containing the testing code you need to add to the project the library file …GT2021.09\cbuilder\lib\Win64\Debug\gtest.a.
I'm not sure how I am supposed to "add to the project the library file". I've tried to
copy the gtest.a and gmock.a files into the project directory and then
right-click on the project name in the "Projects" view of the IDE and select "Add...", then change file type to "static libraries", then select gtest.a and repeat with gmock.a.
Here I've gone ahead and have already added gmock.a because I have experience with googlemock and envision that its additional matchers and mock class generators will help me writing tests.
When I compile a simple test project that does not actually perform any tests, everything compiles and links fine, but when I execute the resulting command line program, then it fails with exit code (errorlevel) -1073741819 and produces no output. This does not happen if I comment all usages of googletest out.
The simple test project which fails during execution consists only of
#include <gtest/gtest.h>
#include <vcl.h>
#include <tchar.h>
int _tmain(int argc, _TCHAR* argv[])
{
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
which should cause googletest to print that 0 tests were executed, but instead it crashes as described. When replacing the two lines in main with a simple printf, which does not use googletest, but leaving all includes unaltered and without altering the project with regard to libraries, it works fine (the new printf prints something) but of course cannot perform any tests.
How to fix this?
One more observation: When adding the static libraries to the project as described above, I get a notification message box from the IDE, saying "One or multiple lines were too long and have been truncated". I have no idea how this message could make sense with regard to adding a static library to the project. It seems however, that this is not an error, and the linker actually uses the static libraries when linking.
The main problem here was the inclusion of the gmock.a library as it was compiled by the GetIt googletest package. This gmock project and basically all other gmock projects in the GetIt package are broken and need to be repaired before using them. I may post more details about this in a future topic. The gmock.cbproj project as distributed by GetIt, e.g., includes the unrelated source file googletest\samples\sample8_unittest.cc, among other errors.
A simple method to use googletest with C++Builder 11.2, which is based on the blog posts by Cigol, but which does not require to copy include files and library files:
When installing googletest with the getit package manager, the IDE automatically opens a group project Googletest.groupproj and compiles two of the contained projects (gtest and gtest_main) for the Windows 64 bit platform in "Release" mode. Furthermore, all other project files in the Googletest project group are modified probably because they have been updated from an earlier C++Builder version and want to be saved when closing the IDE.
There is no need to compile googletest in "Debug" mode, one would need that only for debugging the unit testing framework itself.
Next, create a new VCL Windows 64 bit console application to start using googletest:
File -> New -> "Console Application - C++Builder"
Source Type: C++, Target Framework: Visual Component Library, [OK]
Add Target Platform Windows 64-Bit in the "Projects" view (right-click on Target Platforms).
Delete Target Platform Windows 32-Bit.
Save all in a dedicated directory:
File -> Save All
Create a new folder, e.g. MyUnitTests.
Place project file as e.g. MyUnitTests.cbproj into that folder.
Rename File1.cpp to MyTestsMain.cpp and store in that folder
This creates a C++ source file MyTestsMain.cpp with some includes and an empty main function:
#include <vcl.h>
#include <tchar.h>
int _tmain(int argc, _TCHAR* argv[])
{
}
For convenience, googletest provides a library gtest_main.a which only contains a main function that one can use to execute all unit tests compiled into an executable. By linking against the gtest_main.a library, users can avoid writing their own main function and concentrate on only writing test code. But since the C++Builder wizard has already created a main function, one can as well fill the generated main function with the necessary boilerplate code (only two lines are required, compare against the googletest main function in C:\Users\yourLogin\Documents\Embarcadero\Studio\22.0\CatalogRepository\GoogleTest-2021.09\googletest\src\gtest_main.cc) and add the gtest.h include directive:
#include <gtest/gtest.h>
#include <vcl.h>
#include <tchar.h>
int _tmain(int argc, _TCHAR* argv[])
{
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
Trying to build this project fails because the gtest/gtest.h include file is not found. This can be fixed in Project -> "Options..." -> Building -> C++ Shared Options -> "Include path": After selecting "All configurations - All platforms" in the drop-down list "Target", add the following entry to "Include path":
$(BDSCatalogRepository)\GoogleTest-2021.09\googletest\include
Using the variable $(BDSCatalogRepository) avoids machine- and developer-specific absolute PATHs. Save the changed project settings with File -> "Save all". Trying again to build this project now fails because of different errors, which is progress! The errors now are "Unresolved external"s, which means we have to tell the project to link against gtest.a and where to find it. Linking against gtest.a can be done by adding a pragma to the top of the file containing the main function:
#pragma comment(lib,"gtest")
#include <gtest/gtest.h>
#include <vcl.h>
#include <tchar.h>
int _tmain(int argc, _TCHAR* argv[])
{
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
Where to find the library can be configured in Project -> "Options..." -> Building -> C++ Shared Options -> "Library path": Again first select "All configurations - All Platforms", then add the following entry to "Library path":
$(BDSCatalogRepository)\GoogleTest-2021.09\cbuilder\lib\$(Platform)\Release
After File -> "Save All", a new, clean build generates different "Unresolved external"s, progress! This time, symbols from the standard C++ library are missing, which can be fixed via Project -> "Options..." -> Building -> C++ Linker, again for Target "All configurations - All platforms", check the checkbox "Link with Dynamic RTL, Windows...". After another File -> "Save All", a clean build succeeds and executing the generated Win64\Debug\MyUnitTests.exe generates this output:
[==========] Running 0 tests from 0 test suites.
[==========] 0 tests from 0 test suites ran. (0 ms total)
[ PASSED ] 0 tests.
One can now add tests to the test project. Tests can be added to the source file which contains the main function or to different, topic-specific source files. I'll add two tests in new files for demonstration:
In the "Projects" view, right click on the current project, which is confusingly named "MyUnitTest.exe" in the project view with an ".exe" extension instead of a project file extension, then select "Add new..." -> Unit in the popup menu. "Unit" here is C++Builder's language for a pair of one source and one header file, and is not necessarily related to unit testing.
The new files are initially named "Unit1.cpp" and "Unit1.h" but can be renamed when doing File -> "Save All". I name this first test file to "SelfContainedTest.cpp" because its test will be self-contained. Add the following code to the .cpp file after the IDE-Generated boilerplate:
#include <gtest/gtest.h>
TEST(SelfContained, Addition) {
EXPECT_EQ(3, 1+2);
EXPECT_GT(3, 2+2);
}
Rebuilding succeeds, execution reveals that the second EXPECT fails as it should, the number 3 is in fact not greater than the sum 2+2. Fix if you like.
In a second test, I want to test non-GUI methods of an existing VCL form. In a real-world scenario, the GUI project and my test project would be part of the same project group and live in the same directory or below the same parent directory, and I would add the VCL form's .cpp file also to the test project with (Project View) -> right click -> "Add..." -> C++Builder unit (*.cpp). My form TAdderForm that I'm using here is a simple form with two VCL TEdit fields for entering numbers and a VCL TLabel to display the sum of the two numbers. The sum is computed in a method
int TAdderForm::add(int num1, int num2)
{
return num1 + num2;
}
which I want to test here. To write the test, I add a new "Unit" to the test project as before, naming the source file "VCLTest.cpp" this time. After the IDE-generated boilerplate, I add this code to the .cpp file:
#include "adderFormx.h"
#include <gtest/gtest.h>
TEST(VCL, Addition) {
// Have to instantiate VCL form before calling its method.
Application->CreateForm(__classid(TAdderForm), &AdderForm);
EXPECT_EQ(3, AdderForm->add(1,2));
EXPECT_GT(3, AdderForm->add(2,2));
delete AdderForm; // Delete no longer used form.
AdderForm = nullptr; // clear pointer, another test may allocate new instance
}
This is basically the same test as before. The second expectation will fail again and needs to be fixed because 3>4 is a wrong expectation. The test uses the global instance pointer "AdderForm" from the form's source file for simplicity, this can be modified if required. If multiple tests want to instantiate the same form, a fixture should be used and the setup and teardown done here inside the test should be moved to the fixture's respective methods, but this is no longer C++Builder specific.
Note that Application->Run() is never called, and no GUI elements actually appear on the screen when executing the tests. I'm restricting tests to non-GUI methods of the GUI classes.
Related
"Failed to set up execution context" when running VC++ unit test with external dependencies
I have a solution (available on Git at this link) including one project (producing a DLL library) and a native unit test. Visual Studio Enterprise 2015 with VC++ On Windows 10 The structure of my solution is the following: ./src +--DelaunayTriangulator.UnitTest | |--DelaunayTriangulatorTest.cpp | |--DelaunayTriangulator.UnitTest.vcxproj +--DelaunayTriangulator | |--DelaunayTriangulator.cpp | |--DelaunayTriangulator.h | |--DelaunayTriangulator.vcxproj |--Triangulator.sln The project My source project works and builds fine. It links some libs (AFAIK, they are basically static libraries) which are just some CGAL stuff I need as dependencies. It also runs fine. If you have a look at the project, you will find that I link those .lib files as part of Linker options: <Link> <AdditionalDependencies>$(CGALDirPath)\build\lib\Debug\CGAL-vc140-mt-gd-4.12.lib;$(CGALDirPath)\auxiliary\gmp\lib\libgmp-10.lib;$(CGALDirPath)\auxiliary\gmp\lib\libmpfr-4.lib;..</AdditionalDependencies> ... </Link> The test project The unit test project has been created by using the native test project walkthrough and template in Visual Studio. The test project is also linking the same .lib files that the source project does. Following is the single test I have: #include "stdafx.h" #include "CppUnitTest.h" #include "../DelaunayTriangulator/DelaunayTriangulator.h" using namespace Microsoft::VisualStudio::CppUnitTestFramework; using namespace CodeAlive::Triangulation; namespace TriangulatorUnitTest { TEST_CLASS(DelaunayTriangulatorTest) { public: TEST_METHOD(PerformTriangulation) { DelaunayTriangulator* triangulator = new DelaunayTriangulator(); int result = triangulator->Perform(); Assert::AreEqual<int>(0, result, L"Wrong result", LINE_INFO()); delete triangulator; } }; // class } // ns Before I linked those .lib files from CGAL, the project did build but did NOT run at all, showing this error message: Message: Failed to set up the execution context to run the test The error As soon as I added the .lib files, the project did build and the single unit test did run only if I left the Assert line uncommented (I had to comment all the code referencing my source project): TEST_CLASS(DelaunayTriangulatorTest) { public: TEST_METHOD(PerformTriangulation) { Assert::AreEqual<int>(0, 0, L"Wrong result", LINE_INFO()); } }; When I uncomment the code referencing my project (using the classes I define in my source project), then the same error message shows up when I try running the test: TEST_CLASS(DelaunayTriangulatorTest) { public: TEST_METHOD(PerformTriangulation) { DelaunayTriangulator* triangulator = new DelaunayTriangulator(); int result = triangulator->Perform(); Assert::AreEqual<int>(0, result, L"Wrong result", LINE_INFO()); delete triangulator; } }; I understand that this is due to some kind of issue with external references. What is wrong here?
So the issue here was kinda peculiar to my configuration but also generic enough to deserve an answer for other devs who might incur in this situation. The problem was that the .dlls of my source project were not deployed to the test output folder. So you need to set OutDir in your test project properties: <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <LinkIncremental>true</LinkIncremental> <OutDir>$(ProjectDir)$(Platform)\$(Configuration)\</OutDir> </PropertyGroup> This will make the test actually copy the dlls not in the solution folder, but in the test project folder, and then the referenced source project dlls will be correctly copied. The test project file did not have an entry for OutDir, it seems that made MSBuild not copy the source artifacts.
Linking google test to your main project
I am new to the gtest. I have followed a tutorial how to set it up in the VS 2105. But all that I could find talked about how to build and link gtest. I am passed that level. The code below runs and passes the first dummy test. #include "gtest/gtest.h" TEST(VI, simple) { EXPECT_EQ(false, false); } int main(int argc, char* argv[]) { testing::InitGoogleTest(&argc, argv); RUN_ALL_TESTS(); std::cin.get(); return 0; } My question: How do I exactly hook it up to my project that I want to test? Both gtest project and my "code" project are in the same solution. As far as I understood from reading numerous tutorials, I need 2 things: 1) to include my .h of the class I am about to test (easy and done) 2) To compile my "code" project into a static lib and then hook up the lib to gtest project so I can create and test objects from the "code" project. I am struggling with the point 2. How exactly do I go about it? Thank you for help in advance.
Add a new empty Win32 project to your solution, in its properties select Project Type "static library (.lib)" Move all your sources except the main() function to that project Add a reference to the .lib project to both your main application project and the google test project
Code coverage error (No binaries were instrumented)
Problem: Microsoft Visual Studio Enterprise 2015 Version 14.0.25431.01 Update 3 I'm attempting to use the code coverage function but it returns this error: Empty results generated: No binaries were instrumented. Make sure the tests ran, required binaries were loaded, had matching symbol files, and were not excluded through custom settings. For more information see http://go.microsoft.com/fwlink/?LinkID=253731 My .coverage file is full of non-sense, starting with "PCHÿ". I thought my problem looked similar to this one: Issue with Code Coverage in VS 2012, but deleting the .suo file and running Visual Studio in admnistrator didn't solve anything. How to replicate: 1) Create new empty project "MyProject" 2) Add new file "Calculator.hpp" #pragma once class Calculator { public: int add(int a, int b); int sub(int a, int b); }; 3) Add new file "Calculator.cpp" #include "Calculator.hpp" int Calculator::add(int a, int b) { return a + b; } int Calculator::sub(int a, int b) { return a - b; } 4) Add new file main.cpp #include "Calculator.hpp" #include <iostream> using std::cout; int main() { Calculator calc; std::cout << calc.add(5, 11) << std::endl; std::cout << calc.add(11, 1) << std::endl; return 1; } 5) Build solution. (0 errors) 6) Add new test project to solution as explained here: https://msdn.microsoft.com/en-us/library/hh419385.aspx#objectRef: Add new Native Unit Test Project to solution "CalculatorUnitTest" Add "main.obj" and "Calculator.obj" to Linker/Input/Additional Dependencies of "CalculatorUnitTest" Add path to obj files to Linker/General/Additional Library Directories of "CalculatorUnitTest". (In my case: D:\JF\Programming\Tests\MyProject\MyProject\Debug) Add the header directory of "MyProject" to VC++ Directories/Include Directories. (In my case: D:\JF\Programming\Tests\MyProject\MyProject). 7) Replace code in "unittest1.cpp" with: #include "stdafx.h" #include "CppUnitTest.h" #include <Calculator.hpp> using namespace Microsoft::VisualStudio::CppUnitTestFramework; namespace CalculatorUnitTest { TEST_CLASS(UnitTest1) { public: TEST_METHOD(TestMethod1) { Calculator calc; Assert::AreEqual(5, calc.add(2, 3)); } }; } 8) Build solution (0 errors, TestMethod1 appear in Test Explorer) 9) Right-click TestMethod1, "Run Selected Tests" (Test successfully passes) 10) Right-click TestMethod1, "Analyze Code Coverage for Selected Tests" (Code coverage fails). At D:\JF\Programming\Tests\MyProject\Debug, I have both my MyProject.exe and MyProject.pdb with the CalculatorUnitTest.dll.
First of all, I am not sure if Visual Studio 2015 (C++) supports ".exe" type project for the unit test. But you are using ".obj" directly from your project. You need to place ".pdb" file in the same folder. I created a static library project and added the unit test. Same problem on my environment.
Future here. Same problem, except my test target is a Static Library project in the same Solution. MyLib - Code that will be tested. MyLibTests - Project containing the tests. Solution contains both projects. MyLibTests has project Reference to MyLib. <OutDir> (in .vcxproj) aka Output Directory aka $(OutDir) identical in both projects. (My value <OutDir>$(SolutionDir)$(Configuration)_$(Platform)\</OutDir>) On your test project (MyLibTests), go Properties Select [Debug|platform] Linker Debugging Generate Debug Info = Optimize for debugging /DEBUG Mine was initially set for /DEBUG:FASTLINK. Via this social MSDN post I figured it had something to do with the PDB, because MSDN (aka now "learn.microsoft.com") said this is an important step in several places, and I assume PDB are used trace calls, I assume using DbgHelp.dll. And this sort of checklist modified from another social MSDN post: Test project References properly set (MyLib.lib is in the same Solution as MyLibTests.dll) Build order/dependency set/verified. I also have Autorun on Build. Rebuild (this should rebuild dependencies). made sure all test were run(all test run successful) not using optimisation (Profile Guided/Instrumentation etc). <OutDir> aka Ouput directory should be the same, where both MyLibrary.lib/dll/exe ends up with their MyLibrary.pdb since PDB paths are linked in the exe/dll. not using a runsettings file Unload all other projects other than affected ones
Heap error with Google mock test framework
If you download the latest version of Google Mock (1.7.0) there are project files for VS2005 and 2010! The project to test is written in VS2008,so I opened the VS2005 file and converted it for VS2008 and compiled with Multi-threaded Debug (/MTd) Dynamic Library (.dll) In the test solution: Project to test: Configuration type: Dynamic Library (.dll) Runtime library: Multi-threaded Debug (/MTd) UnitTest project: #include <iostream> #include "gmock/gmock.h" #include "gtest/gtest.h" int main(int argc, char **argv) { ::testing::InitGoogleMock(&argc, argv); return RUN_ALL_TESTS(); } Additional Library Directories: ..\..\gmock\msvc\2005\Debug Additional Dependencies: gmock.lib gmock_main.lib Runtime library: Multi-threaded Debug (/MTd) If I run the UnitTest project I get following error: Windows has triggered a breakpoint in Program_UnitTests.exe. This may be due to a corruption of the heap, which indicates a bug in Program_UnitTests.exe or any of the DLLs it has loaded. in xmtx.c: _RELIABILITY_CONTRACT void __CLRCALL_PURE_OR_CDECL _Mtxunlock(_Rmtx *_Mtx) { /* unlock mutex */ LeaveCriticalSection(_Mtx); #ifdef _M_CEE System::Threading::Thread::EndThreadAffinity(); #endif } // <------- STOPPED HERE #endif /* !_MULTI_THREAD */ What is wrong here? Thank you for any help!
Super-short answer: compile googlemock as a static library instead of a dll; that might fix your problem. Much longer answer: Problems like this are typically the result of mismatched compiler settings. These kinds of problems are a pain to diagnose, which is a large part of the reason for the following guidance given in the googletest FAQ: If you compile Google Test and your test code using different compiler flags, they may see different definitions of the same class/function/variable (e.g. due to the use of #if in Google Test). Therefore, for your sanity, we recommend to avoid installing pre-compiled Google Test libraries. Instead, each project should compile Google Test itself such that it can be sure that the same flags are used for both Google Test and the tests. This applies equally to googlemock. Basically, they're suggesting that you compile the googletest & googlemock source code alongside your own code to avoid this problem. They also make this quite easy: check out the fused-src directory of the gmock distribution for a voltron .cc file and the corresponding headers, gmock.h and gtest.h. If you'd like to continue linking against a completely separate library, you'll need to verify that all of the compiler settings match in the VS project. Basically you'll need to check every single configuration in the properties dialog, paying special attention to the toolset, exceptions, preprocessor definitions, RTTI, etc.
getting the right compiler for C++
I am trying to learn c++ but most of the tutorials and books I have read or looked up teaches you this... (I am assuming like most tutorials, they are teaching in the beginning to code either in win32 console or CLR console. In either case the following does not work.) #include <iostream> int main( ) { std::cout << "Hello World\n"; return (0); } The IDE that i have is Visual C++ 2008 Express edition and they accept code like this #include "stdafx.h" int _tmain(int argc, _TCHAR* argv[]) { return 0; } Or like this #include "stdafx.h" using namespace System; int main(array<System::String ^> ^args) { Console::WriteLine(L"Hello World"); return 0; } Honestly I do not no the difference in none of these and I am not sure if I should just download a older compiler so that it works. If someone can tell me what the difference in these are and where to go from there. That will help tremendously. Thanks [Edited] I am trying to do a simple hello world. But I get the error "system can not find path specified." I have screenshot that shows what the error looks like. It also is saying that my project is out of date when I clearly save the file before I build it. Apparently it can not find the executable file. I went to the debug fold and did not see any .exe file. [Edited] Ok, now When I try to build the project I get the following errors 1>------ Rebuild All started: Project: test, Configuration: Debug Win32 ------ 1>Deleting intermediate and output files for project 'test', configuration 'Debug|Win32' 1>Compiling... 1>stdafx.cpp 1>Compiling... 1>test.cpp 1>c:\users\numerical25\desktop\test\test\test.cpp(1) : warning C4627: '#include <iostream>': skipped when looking for precompiled header use 1> Add directive to 'stdafx.h' or rebuild precompiled header 1>c:\users\numerical25\desktop\test\test\test.cpp(6) : error C2653: 'std' : is not a class or namespace name 1>c:\users\numerical25\desktop\test\test\test.cpp(6) : error C2065: 'cout' : undeclared identifier 1>Build log was saved at "file://c:\Users\numerical25\Desktop\test\test\Debug\BuildLog.htm" 1>test - 2 error(s), 1 warning(s) ========== Rebuild All: 0 succeeded, 1 failed, 0 skipped ========== Here is the code I used #include <iostream> #include "stdafx.h" int main( ) { std::cout << "Hello World\n"; return (0); } Note: I tried using it with and without the #include "stdafx.h" When I tried it without the #include "stdafx.h", it said I might be missing it.
Not sure what you're asking. The first two examples you gave are valid C++ programs that should (will) compile with VC++. The third example is a C++/CLI program that must be compiled with the /CLR compiler switch (this is called Managed C++). EDIT: Adding more specific information (from a comment below): The first two examples are standard (native) C++ (albeit, the second example has MS-proprietary macros). They compile to native code. The third is C++/CLI (a "managed" extension to C++). It compiles to managed (.NET) code. Only the third snippet interacts with the .NET framework in any way. All three are absolutely buildable and runnable using the appropriate projects in VS 2008 (no command line necessary)! Based on your latest update, it looks like you have probably modified some project properties and changed some paths. The app is building, but when you try to run it via VS (you should do this with <Ctrl>+F5, by the way), the executable cannot be found (there are several ways you could have messed this up by changing or playing with various settings). Please note the difference between building and running. Building is the process of compiling and linking your source code. Running is launching the resulting executable. You seem to be confused between these (judging from your complaints about the "...out of date" dialog box). It is normal to get the "...out of date" dialog box if you try to run without rebuilding after you have made a change to the project (even if that change is saved). Just make sure you click "yes." You need to build the project before you can run it. My recommendation is to completely delete your project and solution. Create a new empty project, as suggested elsewhere in this now-very-heavyweight thread, and don't modify any project settings. If this doesn't work, something is seriously wrong! ANOTHER EDIT: Just for completion, since this question kept changing: As others have already pointed out, your ultimate problem with the first snippet is the use of precompiled headers (PCH). PCH are turned on by default in new VS C++ projects. Their purpose is to speed compilation when many implementation files include the same set of headers -- preventing the compiler from having to parse the header files for each compilation unit. You have three options: (Recommended) Disable PCH -- Project Properties --> Configuration Properties --> C/C++ --> Precompiled Headers: Set Create/Use Precompiled Header to Not Using Precompiled Headers. (You don't need to do anything with the "stdafx.h" file or the #include for it.) Place your commonly used #includes in "stdafx.h". In your case, you would put #include <iostream> in "stdafx.h". Place your #includes after `#include "stdafx.h". Microsoft requires that the "stdafx.h" be the first included file in a compilation unit.
A minor point, which I don't see elsewhere in the answers: When using precompiled headers, such as your stdafx.h, you need to include them first. Change it to: #include "stdafx.h" #include <iostream> and that should fix the errors about it. Alternatively, it may be easier to simply switch off precompiled headers: Project > Properties > Configuration Properties > C/C++ > Precompiled Headers > Switch first option to "Not using precompiled headers". They can be useful for big projects but will just be awkward and annoying while you're learning, since they have extra rules (like this "must be included first") which aren't requirements of standard C++ .
The "difference" is pedantic. The latter are just Microsoft-specific entry points. As you are learning C++, I recommend you use a compiler, and preferably an operating system that lets you focus on C++, and not the platform. For this I recommend g++, on an Linux distribution such as Ubuntu. Try this tutorial, there are many others that are similar that quickly let you overcome being tied to the tools, and focus on C++.
int main(); int main(int argc, char* argv[]); These are standard C++. int _tmain(int argc, _TCHAR* argv[]); int wmain(int argc, wchar_t* argv[]); These are Windows-specific to handle Unicode arguments. See What is the difference between _tmain() and main() in C++?. int main(array<System::String^>^ args); This is not C++. This is C++/CLI. For best portability, always use the first form. Also, int main(int argc, char** argv, char** envp); This is a usually seen POSIX extension. Windows supports this form of main too. The envp means (pointer to) environment variables. int main(int argc, char** argv, char** envp, char** apple); This is for Mac only, obviously. void main(); And this is wrong (nonstandard, some compilers (e.g. gcc) will reject it).
Visual C++ Express will compile the first example just fine. However, you need to ensure the proper project settings: Create an "Empty Project" "Add a new item..." to the project via the "Project" menu. Select C++ (.cpp) file. Copy/Paste code into new file Press F5 to compile and run. When "Project is out of date" dialog appears, press "Yes" (build the project) The steps above ensure VC++ Express does not treat your file as a special Win32/Windows console application. EDIT: added additional step 5 to prevent "Can't find..." dialog. I managed to get the same dialog by making sure the exe file does not exist, and answering "No" to the build dialog. With a clean, empty project the exe file does not exist yet. It must be built first. If you answer "no" don't build it, VC++ dutifully does not build the exe and later complains about not being able to find it when it tries to run it later.
As STingRaySC pointed out, all three of your examples will compile in VC2008 express; it's just that examples 2 and 3 are what VC2008 Express will load up initially when you create a project (one of the examples is for Managed C++, as STingRaySC mentioned). You can just delete the code in your second example (the C++ Win32 Console Application project) and paste in the more standard hello world program from your first example. It should compile and run just fine in VC2008 Express - it did for me.
I. Precompiled header #include "stdafx.h" is some kind of tricky stuff that comes your way. If you create a project VC will normally switch on precompiled header. This means that one header stdafx.h is created which is compiled only once. This is done to speed up compile time in big environments. If you start C++ it will confuse you. If you use stdafx.h it has to be the first header in the cpp file. II. Unicode (Utf16) int _tmain(int argc, _TCHAR* argv[]) Microsoft uses UTF16 to implement unicode strings. This means you get two versions of main. int main(int argc, char* argv[]) int main(int argc, wchar_t* argv[]) This is also confusing if you start. To simply start you can use whatever editor you want. Create the file. Open a Visdual studio 2008 command prompt cl main.cpp main.exe and you will see Hello World using code from books. Afterwards try to understand some of the settings of VC. But you should always use an empty project. Else you have to care about stdafx, UNICODE, ...
_tmain with the _TCHAR argv is the way the C runtime allows you to handle unicode. If _UNICODE is defined, then _tmain will expand to wmain, and the _TCHAR argument will be of type wchar_t. If _UNICODE is not defined, then _tmain will expand to main, which will be the ANSI standard. Therefore, so long as _UNICODE is not defined, the second snippet you posted is compliant with the standard.
Lots of waxing lyrical and some misinformation for you sift through already, but I suggest following wonsungi's advice. But to clarify his advice: File->New->Project Select Project Type "Win32", then Template "Win32 Console Project" Give the project a name and location OK Select "Application Settings" Check "Empty Project" In the "Solution Explorer", right click the "Sources" folder, then Add->New Item Type the name of the file, in the "name" box using a .cpp extension (you can ignore the templates if you wish). Enter your code in the new file.
Woot!! I figured it out!!! Below is my original code #include <iostream> int main( ) { std::cout << "Hello World\n"; return (0); } It was missing the header file #include "stdafx.h" . So I had to include it in there so I added it like this #include <iostream> #include "stdafx.h" int main( ) { std::cout << "Hello World\n"; return (0); } I was still getting an error like what you see in my edited question at the bottom. So What I did is I took #include and added it in my header file and then it worked!!!!! Even the the books and alot of tutorials show to add #include to the actual cpp, for some reason in express edition I had to add it to header for it to work. I don't know WHY but it's a solution and now it works.
Download and install Dev-C++ on your system. If the code doesn't work on Visual C++, try it out on Dev-C++ (which uses the GCC compiler). You may get the same results or a different error message. Whenever you get an error message you don't understand, do a Internet search for the error message.