I've been trying to include a structure called "student" in a student.h file, but I'm not quite sure how to do it.
My student.h file code consists of entirely:
#include<string>
using namespace std;
struct Student;
while the student.cpp file consists of entirely:
#include<string>
using namespace std;
struct Student {
string lastName, firstName;
//long list of other strings... just strings though
};
Unfortunately, files that use #include "student.h" come up with numerous errors like
error C2027: use of undefined type 'Student'
error C2079: 'newStudent' uses undefined struct 'Student' (where newStudent is a function with a `Student` parameter)
error C2228: left of '.lastName' must have class/struct/union
It appears the compiler (VC++) does not recognize struct Student from "student.h"?
How can I declare struct Student in "student.h" so that I can just #include "student.h" and start using the struct?
Try this new source :
student.h
#include <iostream>
struct Student {
std::string lastName;
std::string firstName;
};
student.cpp
#include "student.h"
struct Student student;
You should not place an using directive in an header file, it creates unnecessary headaches.
Also you need an include guard in your header.
EDIT: of course, after having fixed the include guard issue, you also need a complete declaration of student in the header file. As pointed out by others the forward declaration is not sufficient in your case.
C++, how to declare a struct in a header file:
Put this in a file called main.cpp:
#include <cstdlib>
#include <iostream>
#include "student.h"
using namespace std; //Watchout for clashes between std and other libraries
int main(int argc, char** argv) {
struct Student s1;
s1.firstName = "fred"; s1.lastName = "flintstone";
cout << s1.firstName << " " << s1.lastName << endl;
return 0;
}
put this in a file named student.h
#ifndef STUDENT_H
#define STUDENT_H
#include<string>
struct Student {
std::string lastName, firstName;
};
#endif
Compile it and run it, it should produce this output:
s1.firstName = "fred";
Protip:
You should not place a using namespace std; directive in the C++ header file because you may cause silent name clashes between different libraries. To remedy this, use the fully qualified name: std::string foobarstring; instead of including the std namespace with string foobarstring;.
Your student.h file only forward declares a struct named "Student", it does not define one. This is sufficient if you only refer to it through reference or pointer. However, as soon as you try to use it (including creating one) you will need the full definition of the structure.
In short, move your struct Student { ... }; into the .h file and use the .cpp file for implementation of member functions (which it has none so you don't need a .cpp file).
You've only got a forward declaration for student in the header file; you need to place the struct declaration in the header file, not the .cpp. The method definitions will be in the .cpp (assuming you have any).
Okay so three big things I noticed
You need to include the header file in your class file
Never, EVER place a using directive inside of a header or class, rather do something like std::cout << "say stuff";
Structs are completely defined within a header, structs are essentially classes that default to public
Hope this helps!
You can't.
In order to "use" the struct, i.e. to be able to declare objects of that type and to access its internals you need the full definition of the struct. So, it you want to do any of that (and you do, judging by your error messages), you have to place the full definition of the struct type into the header file.
Related
So I was trying to access a method that is defined in another class and has the prototype in the header. I'm pretty positive I defined it but it keeps popping up undefined reference to SafeCracker.
Main.cpp
#include <iostream>
#include "mystuff.h"
using namespace std;
void BigDog(int KibblesCount);
int main()
{
cout << SafeCracker(1);
return 0;
}
mystuff.cpp
#include <iostream>
using namespace std;
string SafeCracker(int SafeID)
{
return "123456";
}
mystuff.h
using namespace std;
#ifndef MYSTUFF_H_INCLUDED
#define MYSTUFF_H_INCLUDED
string SafeCracker(int SafeID);
#endif // MYSTUFF_H_INCLUDED
Here it tells you that you have an undefined reference, so you don't really have a problem with the prototype.
Had you forgotten to include the header file that contains the prototype you would have gotten something like
main.cpp: In function ‘int main()’:
main.cpp:8:13: error: ‘SafeCracker’ was not declared in this scope
cout << SafeCracker(1);
Your undefined reference is a linker error. The most likely cause would be that you did not use mystuff.cpp when compiling
If you're compiling from the command line, you should give both files as parameters.
If you're using an IDE that calls the compiler, make sure that the file is part of the project.
For example in Code::Blocks right-click on the file name and go "add to project" (If I remember correctly)
It is also possible that you made a typo in the function declaration in mystuff.cpp (that doesn't seem to be the case here though)
Now there is one important thing about your code you should take note of:
It is very bad practice to put a using namespace in a header file.
using namespace std; in a .cpp source file is mostly up to you, and that using statement will only apply to that particular file.
But if you put it in a header file that is meant to be included through #include , the using there will be forced upon any code that includes it.
Here is an example:
main.cpp
#include <iostream>
// including mystuff.h to use that awesome SafeCracker()
#include "mystuff.h"
// I need to use an std::map (basically an associative array)
#include <map>
// the map of my game
class map
{
int tiles[10][10];
};
int main()
{
// The std map I need to use
std::map<int, int> mymappedcontainer;
// The map of my game I need to use
map mytiles;
// The reason why I need to include mystuff.h
cout << SafeCracker(1);
return 0;
}
Normally, my class map should not be a problem since the map I included from the standard library is inside the namespace std, so to use it you would need to go std::map.
The problem here is that, since mystuff.h has using namespace std; in it, the symbol map is already used, and that creates a conflict.
You do not now who will use your header files, or if you will use them again a long time from now, and maybe then you will want to use name that is already used in the std namespace.
I advise you to use std:: before things taken from the standard libraries instead (std::string instead of just string for example)
PS: In C++, "class" refers to a class data structure, and the functions you made here are not part of any class. You should say "defined in another file" or "defined in another translation unit" instead
i have a problem with my program when it compiles. I tried to figure out for like 3-4 hours and still didn't find out how to fix it. The final result is that i want to use struct students in multiple .cpp files without getting the error with multiple definition of.. Can you guys please help me ? Here's the code:
student.h
#ifndef STUDENT
#define STUDENT
#include <string>
using namespace std;
extern int var;
struct students {
char CodSt[20];
string NumeSt;
string PrenSt;
string DenDisc1;
string MedCD1;
string DenDisc2;
string MedCD2;
string DenDisc3;
string MedCD3;
};
#endif
getStudents.cpp
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int var = 0;
extern struct students *student;
void getStudents() {
int i = 0;
ifstream ifs("Curenta.txt");
while(!ifs.eof()) {
ifs >> student[i].CodSt >> student[i].NumeSt >> student[i].PrenSt >> student[i].DenDisc1
>> student[i].MedCD1 >> student[i].DenDisc2 >> student[i].MedCD2 >> student[i].DenDisc3
>> student[i].MedCD3;
if(!ifs.eof()) {
i++;
}
var = i;
}
ifs.close();
}
Compiler error:
In function 'void getStudents()':
[Error] invalid use of incomplete type 'struct students'
[Error] forward declaration of 'struct students'
and same, so on..
Thanks in advance.
If you want to use your struct students you should #include "student.h" file into your .cpp file. What that does is it causes the pre-compiler to "insert" the header file into your source code file, thus providing the correct definition of the struct.
A few side notes about your code (call me pedantic, but it would help you in a long run if you learn these rules early on):
Be consistent in your naming. Your struct is named `students' (plural) but the include file is 'student.h' (singular)
Do not use using namespace ... in your include files. The reason is: what if someone (even you a year from now, when you've forgotten the implementation details of this file) has a different string class with similar semantics but not from the standard library? If such a user includes that students.h file, then "suddenly" all the custom strings become the ones pulled from standard library, ensuring days of fun debugging :)
It is unclear why would you have an extern struct students * student; line in your .cpp file. Either it is a mistake, or (if not) it would be a good idea to provide a short comment explaining why do you need this line
So I'm learning to use a class .h and .cpp files in my program that reads a file containing information about a bank account. Initially the code worked fine, however after creating the .h and .cpp class files, things don't work so smoothly anymore, as I'm getting strange errors that don't make sense to me.
This is my MAIN cpp file:
#include "Bankaccount.h"
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{ string fileName;
cout << "Enter the name of the data file: ";
cin>>fileName;
cout<<endl;
bankAccount object(fileName);
return 0;
}
This is my Bankaccount.h file
#ifndef BANKACCOUNT_H
#define BANKACCOUNT_H
#include <iostream>
#include <fstream>
#include <string>
class bankAccount
{
public:
bankAccount(string n);
bankAccount();
private:
ifstream sourceFile;
}
And lastly this is the Bankaccount.cpp file
#include "Bankaccount.h"
#include <iostream>
#include <fstream>
#include <string>
bankAccount::bankAccount(string n)
{
sourceFile.open(n.c_str());
}
Which is now generating these errors:
include\Bankaccount.h|13|error: expected ')' before 'n'|
include\Bankaccount.h|18|error: 'ifstream' does not name a type|
include\Bankaccount.h|14|note: bankAccount::bankAccount()|
include\Bankaccount.h|14|note: candidate expects 0 arguments, 1 provided|
include\Bankaccount.h|4|note: bankAccount::bankAccount(const bankAccount&)|
include\Bankaccount.h|4|note: no known conversion for argument 1 from 'std::string {aka std::basic_string}' to 'const bankAccount&'|
I think it might be an issue with the headers? I went a little bit crazy and put all of my relevant headers on each file trying to get it to work.
using namespace std;
This is considered a bad programming practice, and you will do yourself a favor if you forget that this is actually a part of C++ language. Although there are proper situations where one would employ using namespace, this should be avoided until one has a much better technical understanding of C++, its structure, and its grammar; in order to recognize and understand when this can be used correctly (if at all).
In your main() you have:
string fileName;
There is no such class in the C++ library whose name is string. The class's correct name is std::string; however by shoving using namespace std; a few lines above, you end up blissfully unaware of this basic, fundamental fact.
Now, after you understand this, let's go back and look at your header file:
ifstream sourceFile;
Well, there's no such class in the C++ library called ifstream, either. The class's proper name is std::ifstream. All classes and templates from the C++ library exist in the std namespace.
However, because when you #included the header file your using namespace std; alias is not yet defined, your compiler doesn't recognize the class name, and you get this compilation error as a reward.
The solution is not to cram a using namespace std; in your header file. That will simply lead to more chaos and confusion. The proper fix is:
Remove using namespace std; from your code, completely.
Use full names of all classes from the C++ library, everywhere. Replace all references to string, ifstream, and everything else, with their actual class names: std::string, std::ifstream, and so on. Get into the habit of explicitly using the std namespace prefix every time. It might seem like a bother at first, but you'll quickly pick up the habit before long, and you won't think of it twice.
And you'll never be confused by these kinds of compilation errors ever agin.
I have a multifile program, and I can't figure out why my program says that "Customers" (in the registerNewUser() function) is an undeclared identifier.
proc.h
#ifndef PROC_H
#define PROC_H
#include <iostream>
#include "const.h"
#include "customers.h"
#include <fstream>
using namespace std;
void registerNewUser(Customers cBase); // Add new user.
#endif // !PROC_H
I have included the header file (customers.h) with the Customers class also.
customers.h
#ifndef CUSTOMERS_H
#define CUSTOMERS_H
#include <iostream>
#include "const.h"
#include "proc.h"
#include "customer.h"
using namespace std;
class Customers {
private:
char* current;
List* customerList; // List for customers.
public:
Customers(); // Constructor.
~Customers(); // Destructor.
void handler(); // Customers handler/menu.
void addNew(char username[]);
};
#endif // !CUSTOMERS_H
Can anyone see what's wrong?
You have a circular include. customers.h includes proc.h so basiacally
void registerNewUser(Customers cBase);
Will get added to customers.h before the compiler has seen what a Customer is. It looks like you should just be able to remove the #include "proc.h" in customers.h and it should compile.
As stated in the comments above you should never use using namespace std; in a header file as anything that includes it now has the entire std namespace exposed. You should also get in the habit of only using it in the most narrow scope you can or drop it completely. For further reading on the use of using namespace std; see Why is “using namespace std” in C++ considered bad practice?
Basically including "customers.h" in "customers.h" wouldn't be a problem here, since you have a guard (plus point for that). Nevertheless it is not very nice.
As NathanOliver said it COULD be a problem with the order of the includes but it doesn't have to. If you include proc.h first everything is fine. If you include customers first, the compiler includes proc.h before he sees the customer class. proc then wont include customers.h (since its guard prevents it). Then he will find your function not knowing what "Customer" means. So depending on the include order of your header files it will or will not work.
If you want a hint: I normally first only include the necessary files for a forward declaration, then do a forward declaration. Then I include the files necessary files for the definition of the class (These will already know that the class exists). The complete class declaration (with member function declaration) follows. If you do it like this you can avoid many mistakes. In your case:
#ifndef CUSTOMERS_H
#define CUSTOMERS_H
class Customers;
#include "proc.h"
#include "ListTool2B.H"
using namespace std;
class Customers
{
private:
char* current;
List* customerList; // List for customers.
public:
Customers(); // Constructor.
~Customers(); // Destructor.
void handler(); // Customers handler/menu.
void addNew(char username[]);
};
#endif
This is probably a duplicate: you have proc.h including customers.h and customers.h including proc.h this will cause a circular reference, and looks like proc.h included in customers is not necessary, so you could try simply to delete this line:
#include "proc.h"
I am having problems with a class I am writing. I have split the class into a .h file that defines the class and an .cpp file that implements the class.
I receive this error in Visual Studio 2010 Express:
error C2039: 'string' : is not a member of 'std'
This is the header FMAT.h
class string;
class FMAT {
public:
FMAT();
~FMAT();
int session();
private:
int manualSession();
int autoSession();
int mode;
std::string instructionFile;
};
This is the implementation file FMAT.cpp
#include <iostream>
#include <string>
#include "FMAT.h"
FMAT::FMAT(){
std::cout << "manually (1) or instruction file (2)\n\n";
std::cin >> mode;
if(mode == 2){
std::cout << "Enter full path name of instruction file\n\n";
std::cin >> instructionFile;
}
}
int FMAT::session(){
if(mode==1){
manualSession();
}else if(mode == 2){
autoSession();
}
return 1;
}
int FMAT::manualSession(){
//more code
return 0;
}
this is the main file that uses this class
#include "FMAT.h"
int main(void)
{
FMAT fmat; //create instance of FMAT class
fmat.session(); //this will branch to auto session or manual session
}
My inability to fix this error is probably a result of me not understanding how to properly structure a class into separate files. Feel free to provide some tips on how to handle multiple files in a c++ program.
You need to have
#include <string>
in the header file too.The forward declaration on it's own doesn't do enough.
Also strongly consider header guards for your header files to avoid possible future problems as your project grows. So at the top do something like:
#ifndef THE_FILE_NAME_H
#define THE_FILE_NAME_H
/* header goes in here */
#endif
This will prevent the header file from being #included multiple times, if you don't have such a guard then you can have issues with multiple declarations.
Your FMAT.h requires a definition of std::string in order to complete the definition of class FMAT. In FMAT.cpp, you've done this by #include <string> before #include "FMAT.h". You haven't done that in your main file.
Your attempt to forward declare string was incorrect on two levels. First you need a fully qualified name, std::string. Second this works only for pointers and references, not for variables of the declared type; a forward declaration doesn't give the compiler enough information about what to embed in the class you're defining.
Take care not to include
#include <string.h>
but only
#include <string>
It took me 1 hour to find this in my code.
Hope this can help