Order of header file inclusions and dependencies - c++

I'm just trying to test splitting code into multiple files.
I have:
//testMultiple.cpp
#include <string>
#include <iostream>
#include "testInclude.cpp"
int main(){
std::cout << "hi";
}
and
//testInclude.cpp
class testClass{
public:
string x;
};
This is giving testInclude.cpp:3:9: error: ‘string’ does not name a type
I thought since it was including before it included the testInclude.cpp, string would be defined for use in testInclude.cpp.

You need to use std::string instead of string.

You're including a cpp file, not a hpp file.
Common practice is to include header (h/hpp) files, not implementation (c/cpp) files.
If you only compile testMultiple.cpp, this should work. If the compiler is compiling testInclude.cpp separately, it will not see the `#include
Try renaming testInclude.cpp to testInclude.hpp and ensure it is not being compiled.
Here's an example:
///// testInclude.h
#include <vector>
class testClass{
public:
std::vector<int> x; // vector is in std namespace
};
///// testMultiple.cpp
// #include <vector> - gets this through testInclude.h
#include "testInclude.h"
int main(){
}

Use
class testClass{
public:
std::string x;
};

Related

VScode "iostream" file not found in .h file while it's ok in .cpp file

When I'm writing a header file, the editor can't find <iostream>. And the std namespace can't be detected as well.
num.h
#include "tag.h"
#include "token.h"
#include <iostream>
#include <stdio.h>
#include <string>
#ifndef NUM_H_
#define NUM_H_
class Num : public Token {
public:
int value;
Num(int v) : Token(Tag::NUM) { value = v; };
std::string toString() {return " "+std::to_string(value);}
};
#endif
But the strange thing is, when I create a file that includes this header file, and write some demo code to test if this header file really works, then it works fine.
num.cpp
#include "num.h"
int main() {
Num n(1);
std::string a = n.toString();
std::cout<<a;
}
Here is what I get after running it:
I also find that it's fine to write #include <iostream> in the .cpp file, there won't be any error.
It's quite strange, I don't know what's wrong. Maybe it's a bug in VScode?

Why am I getting a "declaration is incompatible with (x)"?

I'm creating a class called person right now in separate header and cpp files.
And for one of the functions I'm getting this error:
declaration is incompatible with "Person::stat Person::getStat()" (declared at line 26 of "C:...")
(Not the exact directory but you get the idea)
Here is the code in the header file:
#pragma once
#include <string>
#include <iostream>
class Person
{
public:
struct stat {
int str;
int end;
int dex;
int intel;
};
Person();
~Person();
//properties
stat getStat();
};
Here is the code in the cpp file:
#include "pch.h"
#include "Person.h"
#include <string>
#include <iostream>
Person::Person()
:age(12), height(0)
{
}
Person::~Person()
{
}
struct stat Person::getStat() {
}
I'm getting the error with the getStat() function. I've tried including the string and iostream headers in both file and also only in the header file since a similar post suggested it. Both didn't solve my problem however.
Should be
Person::stat Person::getStat() {
}
Your version declares a new struct stat which isn't the same as Person::stat.
struct stat Person::getStat() is a method that returns a stat that belongs to the global namespace, not to Person:
Person::stat Person::getStat()
Note that there is no struct here (to avoid declaring one). In C++, we don't use struct after the type has been declared.

C++ Interface (Header) and Implementation File Won't Work

I am taking a C++ class, and for some reason I can't get the classes in my header file to work on one of my programs. I am using Visual Studio 2017, and I added both my header file and my implementation file together with my test file by using the Solution Explorer in Visual Studio.
I have two constructors in my program, one default and one not. I tried deleting the second one from each file, and the program ran, but I can't get it to work otherwise.
Header File:
#pragma once
class BuckysClass {
public:
BuckysClass();
BuckysClass(string);
void coolSaying();
};
Implementation File:
#include "stdafx.h"
#include <iostream>
#include "BuckysClass.h"
#include <string>
using namespace std;
BuckysClass::BuckysClass() {
cout << "Bucky is ";
}
BuckysClass::BuckysClass(string x) {
cout << x;
}
void BuckysClass::coolSaying() {
cout << "preachin to the choir" << endl;
}
Test File:
#include "stdafx.h"
#include <iostream>
#include <string>
#include "BuckysClass.h"
using namespace std;
int main() {
BuckysClass buckysObject;
buckysObject.coolSaying();
BuckysClass buckysObject2("Bucky is not ");
buckysObject2.coolSaying();
system("Pause");
return 0;
}
syntax error:identifier 'string'
#include <string>//include the string header
class BuckysClass {
public:
BuckysClass();
BuckysClass(std::string);//add the namespace identifier
void coolSaying();
};
Your header file BuckysClass.h does not have the <string> Header file included.
Add:
#include<string>
using namespace std;
you should remove these includes from the corresponding .cpp file and just keep BuckysClass.h in cpp files.
Here are some more pictures of the test file and the error message I got that I couldn't post above.
Test File
Error Messages

C++ class in separate file not compiling. Already defined in Class.obj one or more multiply defined symbols found

So I've done extensive googling and searching on StackOverflow and am unable to find a solution despite several answers with this exact issue.
I am trying to create a test class in an external file called Fpc5.cpp
It's contents are:
Fpc5.cpp
#include "stdafx.h"
#include "Fpc5.h";
#include <iostream>
using std::cout;
class Fpc5 {
int bar;
public:
void testMethod();
};
void Fpc5::testMethod() {
cout << "Hey it worked! ";
}
and my main .cpp file:
Test.cpp
// Test.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "iostream"
//#include "Fpc5.cpp"
#include "Fpc5.h";
using std::cout;
using std::cin;
using std::endl;
int main()
{
cout << "Hello" << endl;
Fpc5 testObj;
testObj.testMethod();
system("pause");
return 0;
}
all the answers I've read indicate this is caused becaused I used to be including the class in the main file itself which is why I created a header file
Fpc5.h
#pragma once
void testMethod();
This changed the error, but still did not fix the issue. Currently my Test.cpp does not recognize a Fpc5 class. I've also tried adding the Fpc5.cpp and Fpc5.h in stdafx.h and that still does not resolve the issue.
stdafx.h
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#pragma once
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
// TODO: reference additional headers your program requires here
//#include "Fpc5.cpp"
#include "Fpc5.h"
I'm sure this a simple syntax/conceptual understanding error, but I'm quite new to c++ and am not sure what is wrong.
This is definition of your class and it must be in Fpc5.h
class Fpc5 {
int bar;
public:
void testMethod();
};
Then, you have Fpc5.cpp where you implement methods of the class:
#include "Fpc5.h" // Compiler needs class definition to compile this file!
void Fpc5::testMethod()
{
}
And then you can use Fpc5 class in Test.cpp
#include "Fpc5.h"
int main()
{
Fpc5 foo;
foo.testMethod();
return 0;
}
As an alternative you can pack everything into Test.cpp
Move the definition of your class:
class Fpc5 {
int bar;
public:
void testMethod();
};
to the header file, "Fpc5.h".
Implement the methods to "Fpc5.cpp".

Redefinition of class

I got three .cpp files and two header files.
But when i compile them, meaning the Point.cpp, Data.cpp and main.cpp, it will say
Data.h:6:7 redefinition of Data at 'Data.h'
Data.h:6:7 previously definition of 'class Data'
Below is my Data.h(previously known as 2.h at above)
#include <iostream>
#include <string>
using namespace std;
class Data
{
private:
string sType;
public:
Data();
Data(string);
void setSType(string);
string getSType();
};
Below is my data.cpp
#include "Data.h"
Data::Data()
{
sType = "";
}
Data::Data(string s)
{
sType = s;
}
void Data::setSType(string ss)
{
sType = ss;
}
string Data::getSType()
{
return sType;
}
Below is my PointD.h (previously known as 3.h)
#include <iostream>
#include <string>
#include "Data.h"
using namespace std;
class PointD
{
private:
int x
Data data1;
public:
PointD();
PointD(int,Data);
void setX(int);
void setData(Data);
int getX();
Data getData();
};
Below is my PointD.cpp
#include "PointD.h"
PointD::PointD()
{
x = 0;
}
PointD::PointD(int xOrdinate,Data dd)
{
x = xOrdinate;
data1 = dd;
}
void PointD::setXordinate(int Xordinate)
{
x = Xordinate;
}
void PointD::setData(Data dd)
{
data1 = dd;
};
int PointD::getXordinate()
{
return x;
}
Data PointD::getData()
{
return data1;
}
This is my main.cpp
#include <iostream>
#include <string>
#include "Data.h"
#include "PointD.h"
using namespace std;
int main()
{
const int MAX_NUM = 20;
Data ldata[MAX_NUM];
PointD pointd[MAX_NUM];
//more codes..
}
But when i compile them, meaning the Point.cpp, Data.cpp and main.cpp, it will say
Data.h:6:7 redefinition of Data at 'Data.h'
Data.h:6:7 previously definition of 'class Data'
Can anybody let me know whats actually went wrong here..
You need to use include guards, or the easiest:
#pragma once
in your header files
See Purpose of Header guards for more background
Idea: 1.hpp
#ifndef HEADER_GUARD_H1_HPP__
#define HEADER_GUARD_H1_HPP__
// proceed to declare ClassOne
#endif // HEADER_GUARD_H1_HPP__
In each of your header files write:
#ifndef MYHEADERNAME_H
#define MYHEADERNAME_H
code goes here....
#endif
Its better like this:
#ifndef DATA_H /* Added */
#define DATA_H /* Added */
#include <iostream>
#include <string>
// using namespace std; /* Removed */
class Data
{
private:
std::string sType;
public:
Data();
Data( std::string const& ); // Prevent copy of string object.
void setSType( std::string& ); // Prevent copy of string object.
std::string const& getSType() const; // prevent copy on return
std::string& getSType(); // prevent copy on return
};
#endif /* DATA_H */
The big fix is adding ifndef,define,endif. The #include directive works as if copying and pasting the .h to that line. In your case the include from main.cpp are:
main.cpp
-> Data.h (1)
-> Point.h
-> Data.h (2)
At (2), Data.h has already been `pasted' into main.cpp at (1). The class declaration of Data, i.e. "class Data{ .... };" , appears twice. This is an error.
Adding include guards to the top and bottom of every .h are standard practice to avoid this problem. Don't think about it. Just do it.
Another change I'd suggest is to remove any "using namespace ..." lines from any .h . This breaks the purpose of namespaces, which is to place names into separate groups so that they are not ambiguous in cases where someone else wants an object or function with the same name. This is not an error in your program, but is an error waiting to happen.
For example, if we have:
xstring.h:
namespace xnames
{
class string
{
...
};
}
Foo.h
#include <xstring>
using namespace xnames;
...
test.cxx:
#include "Foo.h"
#include "Data.h" // Breaks at: Data( string ); -- std::string or xnames::string?
...
void test()
{
string x; // Breaks. // std::string or xnames::string?
}
Here the compiler no longer knows whether you mean xnames::string or std::string. This fails in test.cxx, which is fixable by being more specific:
void test()
{
std::string x;
}
However, this compilation still now breaks in Data.h. Therefore, if you provide that header file to someone, there will be cases when it is incompatible with their code and only fixable by changing your header files and removing the "using namespace ...;" lines.
Again, this is just good coding style. Don't think about it. Just do it.
Also, in my version of Data.h, I've changed the method parameters and return types to be references (with the &). This prevents the object and all of its state from being copied. Some clever-clogs will point our that the string class's is implementation prevents this by being copy-on-write. Maybe so, but in general, use references when passing or returning objects. It just better coding style. Get in the habit of doing it.