So I'm learning C++ and learning to also use SQLite in my practices for data persistence across application runs, which is lots of fun.
But I bumped into this issue:
The program is a Grade Book, classic Ditel C++ book exercise. I'm structuring my classes as follows:
~/classes/Database.h/cpp // A small wrapper for sqlite3
~/classes/Student.h/cpp // The Student object with name and grades (Uses Database)
~/classes/GradeBook.h/cpp // Takes care of most of the application logic and UI (Uses Database and Student)
~/main.cpp // contains just the main function and base Instances of Database and GradeBook
This is so I can instantiate a Single Database Object from main() and pass it by reference to GradeBook and Student so they can use the Database functions. I tried all possible order of includes and as it turns out only this order has works for me.
Student includes Database.
GradeBook includes Student, gets access to Database.
main.cpp includes GradeBook, gets access to both Database and Student.
The question is, is this right? It seems utterly counter-intuitive that the includes seems to "cascade" backwards from deepest classes to the main.cpp file, in other words, Am I doing this right, or am I missing something?
If so, a little explanation or pointers on how this "cascading" works would be pretty awesome.
Thanks!
First, your header files should use include guards to prevent multiple inclusion:
#ifndef MY_HEADER_H
#define MY_HDEADER_H
// code...
#endif // this file will only ever be copied in once to another file
Secondly, you should explicitly include all of the header files that you need to do what you want to do. Relying on header A to include header B for you is just clunky and, since you're using include guards, you never have to worry about including the same file twice.
So, to answer your question, no, it's not "right" in the sense that it could be "better". main.cpp should include the all of the header files that it needs. All of them. #include is a simple text substitution mechanism. When you #include a file it is literally pasted in. That's it.
Related
I am a tutor and I'm trying to write something to help students learn C++. Suppose I have a .cpp file that includes two .h files, which we will call "solution.h" and "student_answer.h". The "solution.h" file contains a class called "Solution" which implements member functions and variables that solve a problem. Students are to implement their own solution to the same problem in a separate "student_answer.h" file, in a class which we will call "Student".
The .cpp file should then take the two class definitions, "Solution" (the class defined in solution.h) and "Student" (the class defined in student_answer.h), and run the two implementations to verify whether the student answer is correct, and it should provide detailed output in cases where the student answer has a bug. However, I want to be able to hide the contents of the solution.h file (or the "Solution" class) from the students while still providing them with the .cpp file that they can compile and run their own solution with.
Currently, I have something like this:
#include "solution.h"
#include "student_answer.h"
// ...
int main() {
Solution s;
Student a;
// run member functions of s and a, compare results to verify if student
// implementation is correct (and print helpful output if there is a bug)
...
}
Is there a way to do the same thing without having to reveal the solution.h file to the students? Is there a better approach to doing this?
Thanks!
Is there a way to do the same thing without having to reveal the solution.h file to the students?
No.
Best you could do is to not put any implementation details into solution.h and instead provide a pre-compiled library for comparison. That would prevent students from seeing the solution except for the API, which is presumably part of instructions for the student anyway.
This does have a challenge that the pre-compiled library must be compatible with the systems that the students use. This can be solved by instructing the students to use a provided VM or container image.
However, this approach does not prevent the students from implementing their API by delegating to the solution API.
There's really no need to provide the correct solution. Write to solution for yourself only; write tests that are required to pass with either your solution or the student's; Test the tests with your solution; Provide only the tests to the students, not your solution.
Create a static or dynamic library of Solution.h, compile it, and link it with the project. The students now get the header of the solution with declarations, but not definitions.
The library topic is a little bit too complex to explain in one answer. Watch the video from TheChernoProject ( https://www.youtube.com/watch?v=Wt4dxDNmDA8 ) for it.
Another way would be, making the code unreadable (defines) or put it in asm blocks.
I'm trying to use (Ligra) in a project. The framework works as long as the chief header "ligra.h" is included. Trouble is, that header has an implementation of parallel_main, which is a macro wrapper around main with OpenMP trickery. So if I wanted to write a simple program:
#include "ligra.h"
#include <iostream>
int main(){
std::cout<<"Hello World";
return 0;
}
It would not compile. Redefinition of symbol main.
Also, I need a parallel_main, with the exact macro trickery done in the "parallel.h" header.
So I think I have two options:
1) modify the file, add a pair of #ifdef LIGRA_MAIN's and not define the macro at compile time. Thus I can have my own main and not have redefinition. Trouble is I need my project to be using the upstream version of ligra, and Julian Shun, the original developer has probably forgottten about his project (and github, since he ignored more than one pull request).
2) Use/Write a #pragma that would strip that function out at the include stage.
I don't know how to do that last part, and would be very much in your debt if someone who did, reached out.
A solution that does not involve modifying library files (but is somewhat brittle) could be to do the following:
#include "ligra/parallel.h" (this does #define parallel_main main).
#undef parallel_main to prevent this rewriting of function names.
#include "ligra/ligra.h" as usual. Since parallel.h has an include guard, its repeated inclusion is prevented and parallel_main will not be redefined.
Proceed as normal.
You might also want to wrap this into a header so you only have to write it once.
Alternatively, you could do what #user463035818 suggests and redefine main only for the inclusion of ligra.h for very similar effect. The difference is in the names that the parallel_main function(s) from ligra will get.
You can simply not include ligra.h. If there is something useful in that file, then create a copy of the file - excluding the main function - and use that copy.
Sure, that means that if the upstream ligra.h is updated, your copy will not have the corresponding changes. However, given the premise "the original developer has probably forgottten about his project", this is probably not a problem. If the premise is wrong, then a better approach would be to create a pull request to make the framework usable as a library.
I'm trying to freshen up my basic C++ skills after a 2 year break by working on a basic card games program. So I created 3 objects: deck, hand, and card. Everything was working pretty well until I tried to define a global constant deck for the whole program to use and everything got screwed up (the deck is supposed to be all 52 cards in order and is never changed). I'm trying to figure out how to link the following files together:
main.cpp
deck.h
deck.cpp
hand.h
hand.cpp
card.h
card.cpp
Where do I need includes and also where and how do I define my global deck to be used across the program? I made a mess of my existing code to try to include everything in everything and now nothing is compiling correctly. Thanks!
For the deck, just define it in main.cpp. It can be passed by reference to any functions in other classes that would need to manipulate it. As far as headers, #include only the headers you need for the current source file. Including header guards is always a good idea as well, so you don't have to worry about how many times you reference a header.
EDIT
extern was mentioned in another answer. This is necessary if you're actually defining a global object. There are mixed opinions about globals. I've not seen it very often in pure C++.
To answer your question about the global you would declare it as extern in deck.h (I'm assuming that makes sense in your program) and define it in deck.cpp.
For instance:
deck.h
extern Card GLOBAL_DECK[52];
deck.cpp
Card GLOBAL_DECK[52];
Now as for using a global, it is a much better approach to avoid globals, and pass references to an object that lives in a higher scope, or create the object on the heap and pass pointers or references to it (but you have to remember to delete it once you are finished with it).
For the question about where do you need your includes, you should be wrapping each header in include guards like this (replacing HEADER_NAME with the header file name, for instance hand.h becomes HAND_H:
#ifndef HEADER_NAME
#define HEADER_NAME
header contents
#endif //Some people like to put HEADER_NAME here but it isn't really necessary
//unless you are using a lot of precompiler directives, which you shouldn't be
Then include the headers in files that need them. Hand and deck needs card, anything else depends on how you have used them. Since you haven't mentioned which complier/toolset you are using I can't give you specific instructions. But I would compile them by themselves and include what you need to get each file compiling. You may encounter circular dependencies, which means that A requires B to compile which requires A to compile (or a longer chain, but eventually it becomes circular), and you will need to research forward declarations and may need to use references and pointers to solve, or change your design.
Then you need to link the object files together to make an executable. If you are using an integrated IDE like Visual Studio or code::blocks it will do it for you, but you might need to find out what your linker is or set up one if you are using a generic IDE like eclipse.
Global variables (or constants) are declared at the top of a file, below the includes, but above any code.
So for this examples, I would write it simply like this :
#include <iostream>
#include <deck.h>
#include <hand.h>
#include <card.h>
extern deck ... // If we want to use the deck constant anywhere in our program
int main ()
{
...
}
notice that I assumed here that deck is non-constant (which I think would not pose a problem).
But if you absolutely need to use a global constant, you can create a new file, name it deckConstant.cpp for example then write the following in this file :
namespace myGlobalConstant
{
extern const deck ... // put the name of the constant you want
}
and create of course the file deckConstant.h :
#ifndef DECKCONSTANT_H
#define DECKCONSTANT_H
namespace myGlobalConstant
{
extern const deck ...
}
#endif
then in the main.cpp file you just add :
#include <deckConstant.h>
using namespace myGlobalConstant
I hope I understood the question right.
I just started on a few C++ tutorials, and I have run into something that I just can't seem to make much sense of.
In C++ it seems people are using a code file and a header file, for me this just seem inconvinient. Why would I want to swap around between two files just to write a simple getter method.
Is it considered the "correct" way to use headers in C++? Or is it just the tutorial I have picked up that uses this?
I get the idea of splitting code to make it look more clean, but is it good for anything else other than that?
Thanks in advance.
There are some reasons for using hpp(header)- and cpp(code)-files. One of them is the following: A library (dll- or so-file) cannot be "used" like a jar-file in java. If you write a library, you have to provide declarations of the classes, methos,... in form of a hpp-file.
Think about using the class you wrote in other files. If you had the class definition in a separate file, you could help the compiler to figure out how to use the class by including the header file in places where you are planning to use this code.
The compiler only needs to know whether you are using the classes right(it does not care about how to run it, until linking), therefore all you need to give the compiler is the declaration of the class(header file), to do the error checking. When you say "include", the preprocessor just copies and pastes the header file contents into the new file, so that the new file now knows how to use the class you wrote.
A header file in c++ stores alot of information, if c++ have been made using every single "header" file in c++ in each program you make, when you then write a function from iostream for example, the program will go through every single header file just to find the right header file. so instead they made the #inlcude function in c++, so you could specify where your functions are from.
And when you create a program you could make own header files, so the code is more nicely set up. and then instead of having to make alot of lines of code in one main source file, you could import others. like if you are making a game, one header file for Animals and in that header file you have a Class for Cats, and one for dogs. having a more clean code.
In C/C++, headers are used to share the class structure (among other things) between classes.
so one can use
include "classFOO.h"
in classBAR.h (or classBAR.cpp) and use classFOO.
I am working on a traffic simulation program for school. My Simulation class reads in a list of vehicles from an XML file, so I have included Vehicle.h in my Simulation class. I want my vehicle to be able to hold a pointer to the simulation object so that it can use the simulation's searchRoads function. So I included Simulation.h in my Vehicle class.
When I did this, I got over 100 errors when I tried to compile. I'm pretty iffy on my C++ so if I committed some sort of cardinal sin, please let me know how to rectify this.
Either, You are missing inclusion guards, leading to multiple inclusion of header files
Or
You are creating a Circular Dependency of your headers. You should be rather using Forward Declaration.
Post details of your code for more detailed answer.
You learn something about include guards: http://en.wikipedia.org/wiki/Include_guard
Hope this helps.
Since operating systems have the ability to handle long file names I've started naming my include files so they reflect the code's position in the namespace:
namespace network {
class connection { bool send( char* stuff ); }
}
Would end up in the file "network.connection.h".
It helps keep things organized and reduces the chance of name collision of files.