I am new to C++ and I have a problem.I am trying to make to classes mutual friend,and accessing different members in one from the other one.I can't figure out what is that I do wrong.Here is what I have so far:
#ifndef HA_H_
#define HA_H_
#include"Ha2.h"
using namespace std;
class two;
class one{
public:
int tip;
int timp;
one(int t) :tip(t){}
friend class two;
};
#endif /* HA_H_ */
The second header:
#ifndef HA2_H_
#define HA2_H_
#include"Ha.h"
#include<vector>
class one;
class two{
public:
vector<one> v;
vector<int> x;
inline void create_x(vector<one> v){
// vector<one>::iterator it=v.begin();
int i;
for(i=0;i<v.size();i++){
x.push_back(v.at(i).tip);
}
}
friend class one;
};
#endif /* HA2_H_ */
And the main:
#include<vector>
#include<iostream>
#include"Ha.h"
#include"Ha2.h"
int main()
{
one o(3);
two x;
x.v.push_back(o);
x.create_x(x.v);
cout<< x.x.back();
}
And I get several errors like:
class two has no member named 'v'
Any advice?Thank you.
main.cpp includes "Ha.h", which, before using namespace std;, includes "Ha2.h". Then, class two is defined, which declares v as a vector<one> without qualifying vector in the std namespace.
There is no need to include "Ha2.h" in "Ha.h", remove that, then qualify vector.
Forward declarations are used when the class definition has pointers or references. And neither of the class definitions has them and so forward declarations are unnecessary.
Also the headers has both forward declarations and it's corresponding header inclusion which voids the whole purpose of forward declarations.
Include the headers and also the using directive in the source files.
As of now, the program has no methods to test the purpose of friend and so this should at least make the program compile.
Ha.h header :
#ifndef HA_H_
#define HA_H_
class two ; // No pointers or references of two in one.
// So, remove it and place when you actually have
// a method taking reference of two.
class one{
public:
int tip;
int timp;
one(int t) :tip(t){}
friend class two;
};
#endif /* HA_H_ */
Ha.cpp
#include "Ha2.h" // Place this only when have a method accessing
// members of two. Else this is unnecessary.
#include "Ha.h"
using namespace std ;
Ha2.h
#ifndef HA2_H_
#define HA2_H_
class one ; // No pointers or references of one in two.
// So, remove it and place when you actually have
// a method taking reference of one.
class two{
public:
vector<one> v;
vector<int> x;
inline void create_x(vector<one> v)
{
// vector<one>::iterator it=v.begin();
int i;
for(i=0;i<v.size();i++)
{
x.push_back(v.at(i).tip);
}
}
friend class one;
};
#endif /* HA2_H_ */
Ha2.cpp
#include <vector>
#include "Ha.h" // Place this only when have a method accessing
// members of two. Else this is unnecessary.
#include "Ha2.h"
using namespace std ;
// .....
main.cpp
#include <vector> // Definitely need this because in the current unit, Ha2.h is
// included which has a data type of vector<int>
#include <iostream>
#include"Ha.h"
#include"Ha2.h"
using namespace std ; // vector and the other standard definitions are specified
// in std namespace
int main()
{
one o(3);
two x;
x.v.push_back(o);
x.create_x(x.v);
cout<< x.x.back();
}
With the above modifications, you should get rid of errors. If any new errors pop up, post the exact error messages in your question.
Another alternative to remove the circular dependency is to make a separate header file, like decl.h or whatever you want it to be, and inside of that simply put the following lines:
#ifndef DECL_H_
#define DECL_H_
class one;
class two;
#endif DECL_H_
Then in Ha.h and Ha2.h remove the #include "Ha.h" and #include "Ha2.h" lines and replace them with #include "decl.h". Also remove the class one; and class two; declarations in Ha.h and Ha2.h, but keep the definitions of each respective class.
Now you won't have Ha.h depending on Ha2.h and vice versa.
Hope this helps,
Jason
Related
I am trying use a friend function. The function should be a friend to all the classes that i have. But i get multiple errors some of which says incomplete type. The following are files that i have:
main.cpp
#include <iostream>
#include "my_ClassA.h"
#include "my_ClassB.h"
#include "my_ClassC.h"
#include "my_ClassD.h"
int main()
{
std::cout<<"Hello World";
my_namespace::my_ClassA object1;//this will do some computation and set everything up for object1
my_namespace::my_ClassB object2(object1);//this object2 will use object1 to further do other computation
my_namespace::my_ClassC object3(object2);
my_namespace::my_classD object4(object4);
//runComputation(object1, object2, object3, object4);
return 0;
}
my_ClassA.h
#pragma once
#include<string>
#include <vector>
//these three includes are for friend function BUT result in error incomplete type
#include "my_ClassB.h"
#include "my_ClassC.h"
#include "my_ClassD.h"
/////////////////////////////////////////////
namespace my_namespace{
class my_ClassA{
friend void runComputation(my_ClassA&,my_ClassB&,my_ClassC&,my_ClassD&);
private:
std::string name;
std::vector<std::string> vec;
public:
std::vector<std::string> get_vec();
};
void runComputation(my_ClassA&,my_ClassB&,my_ClassC&,my_ClassD&);
}
my_ClassA.cpp
#include "my_ClassA.h"
std::vector<std::string> my_namespace::my_ClassA::get_vec(){
return vec;
}
my_ClassB.h
#pragma once
#include<string>
#include <vector>
#include "my_ClassA.h"
#include "my_ClassC.h"
#include "my_ClassD.h"
namespace my_namespace{
class my_ClassB{
friend void runComputation(my_ClassA&,my_ClassB&,my_ClassC&,my_ClassD&);
private:
std::string name;
std::vector<std::string> vec;
public:
std::vector<std::string> get_vec();
my_ClassB(my_ClassA);
my_ClassB(){
;
}
};
}
my_ClassB.cpp
#include "my_ClassB.h"
std::vector<std::string> my_namespace::my_ClassB::get_vec(){
return vec;
}
my_namespace::my_ClassB::my_ClassB(my_ClassA temp_objA){
;
}
my_ClassC.h
#pragma once
#include<string>
#include <vector>
#include "my_ClassB.h"
#include "my_ClassA.h"
#include "my_ClassD.h"
namespace my_namespace{
class my_ClassC{
friend void runComputation(my_ClassA&,my_ClassB&,my_ClassC&,my_ClassD&);
private:
std::string name;
std::vector<std::string> vec;
my_ClassB objB;
public:
my_ClassC(my_ClassB);
std::vector<std::string> get_vec();
};
}
my_ClassC.cpp
#include "my_ClassC.h"
#include "my_ClassB.h"
std::vector<std::string> my_namespace::my_ClassC::get_vec(){
return vec;
}
my_namespace::my_ClassC::my_ClassC(my_ClassB temp_objB){
;
}
my_ClassD.h
#pragma once
#include<string>
#include <vector>
#include "my_ClassA.h"
#include "my_ClassB.h"
#include "my_ClassC.h"
namespace my_namespace{
class my_ClassD{
friend void runComputation(my_ClassA&,my_ClassB&,my_ClassC&,my_ClassD&);
private:
std::string name;
std::vector<std::string> vec;
my_ClassA objA;
public:
std::vector<std::string> get_vec();
};
}
my_ClassD.cpp
#include "my_ClassD.h"
std::vector<std::string> my_namespace::my_ClassD::get_vec(){
return vec;
}
I tried using the getters of each of the classes in the main.cpp. But some my classes have large size vectors,sets etc etc. So i do not want to copy them again and again. So instead i want to access the data members of the classes directly in a function called runComputation. And that function will be taking the object created as references so that copy doesn't happen inside main.cpp.
What i have is this: First i create different objects which may take the previously created object as input in main.cpp. After all the objects are created successfully, i want to run some computation on those objects. Now the problem is that i can use the getters and setters of the objects created in the main.cpp file. But the objects have large vectors and other objects inside them, and so they will be copied each time i use them in a for loop using getters. To avoid this i want to create a friend function that can take these objects as references and avoid copying. How can i resolve this ? And is there any better way of achieving this?
PS: I am aware of ADL. Will ADL be used when i write a friend declaration like friend void runComputation(someobject&); and then after the class to make this friend function visible void runComputation(someobject&);
Make a my_forwards.h header file. It contains
namespace my_namespace {
class my_ClassA;
class my_ClassB;
class my_ClassC;
class my_ClassD;
}
(or just write this manually at the top of every header file).
Now don't include my_ClassA.h in the other headers at all. If you have the body of a function in my_ClassB that requires the definition of my_ClassA, put it in a .cpp file instead of in the header.
// my_forwards.h
namespace my_namespace {
class my_ClassA;
class my_ClassB;
class my_ClassC;
class my_ClassD;
void runComputation(my_ClassA&,my_ClassB&,my_ClassC&,my_ClassD&);
}
// my_ClassA.h
#pragma once
#include<string>
#include <vector>
#include "my_forwards.h"
namespace my_namespace{
class my_ClassA{
friend void runComputation(my_ClassA&,my_ClassB&,my_ClassC&,my_ClassD&);
private:
std::string name;
std::vector<std::string> vec;
public:
std::vector<std::string> get_vec();
};
}
// my_ClassA.cpp
#include "my_ClassA.h"
// include other my_ClassX here if needed, after my_ClassA.h
// implementation of my_ClassA:
std::vector<std::string> my_namespace::my_Class::get_vec() {
return vec;
}
In some cases this may require declaring a destructor/constructor in a header file, and doing a my_ClassA::my_ClassA()=default; in the cpp file.
Now, your my_ClassC has a member variable of type my_ClassB. This is a case where you have to #include "my_ClassB.h" in the my_ClassC.h header file, because my_ClassC needs the definition of my_ClassB. But in most cases, either a forward declaration is good enough, or slight modification (changing a value parameter to a reference one, for example) is good enough that you don't have to cross-include the header files.
Don't use return by value to avoid copying large vectors, return const reference to access data or non-const reference to modify.
E.g., header:
#pragma once
#include<string>
#include <vector>
//these three includes are for friend function BUT result in error incomplete type
#include "my_ClassB.h"
#include "my_ClassC.h"
#include "my_ClassD.h"
/////////////////////////////////////////////
namespace my_namespace{
class my_ClassA{
friend void runComputation(my_ClassA&,my_ClassB&,my_ClassC&,my_ClassD&);
private:
std::string name;
std::vector<std::string> vec;
public:
// use this getter to modify inner data by reference
std::vector<std::string>& get_vec();
// use this getter to access data by const referenct
std::vector<std::string> const & get_vec() const;
};
void runComputation(my_ClassA&,my_ClassB&,my_ClassC&,my_ClassD&);
}
implementation:
#include "my_ClassA.h"
std::vector<std::string>& my_namespace::my_ClassA::get_vec() {
return vec;
}
std::vector<std::string> const & my_namespace::my_ClassA::get_vec() const {
return vec;
}
You may want to refactor classes to a chain of function calls:
// class or struct which contains intermediate state
State state;
runComputation1(&state);
runComputation2(&state);
runComputation3(&state);
runComputation4(&state);
The problem is due to circular dependency of different files. Instead of including the headers just use forward declarations for different class parameters and the issue is resolved.
I'm trying to create a vector which will store objects. I have added to the header file of the class as a private data member.
I am trying to initialize this vector as being empty (so that I can add objects to it later on in the program) but when I compile this program to test, this error is returned:
...error: '_bookingVector' was not declared in this scope|
I think the problem is with my initialization list on my default constructor(_bookingVector is obviously the vector):
Schedule::Schedule() : _bookingVector()
{ }
Is my syntax wrong? Or are vectors initialized differently?
Here is my code:
Schedule.h
#ifndef SCHEDULE_H
#define SCHEDULE_H
#include "Booking.h"
#include <vector>
using namespace std;
class Schedule
{
public:
Schedule();
void AddBooking(int bday, int btime, int btrainer, int bid);
void RemoveBooking(int bday, int btime);
void DisplaySchedule();
void DisplayAvailableTimeSlots();
//For Testing
void DisplayDebug();
private:
vector<Booking> _bookingVector;
};
#endif // SCHEDULE_H
Schedule.cpp
#include "Schedule.h"
#include "Booking.h"
#include <vector>
#include <iostream>
Schedule::Schedule() : _bookingVector()
{ }
void AddBooking(int bday, int btime, int btrainer, int bid){
Booking bookingObject(bday, btime, btrainer, bid);
_bookingVector.push_back(bookingObject);
}
void DisplayDebug(){
for(int i = 0; i < _bookingVector.size(); ++i){
cout << _bookingVecotr[i] << endl;
}
}
I'm very eager to learn what I'm doing wrong and fix it.
The issue is not with the constructor, which looks fine if unnecessary1. The issue is that you have defined AddBooking and DisplayDebug as non-member functions, but these should be members in order to access other members of the class.
Modify the definitions to be in the scope of the Schedule class thus:
void Schedule::AddBooking(int bday, int btime, int btrainer, int bid) { ...
^^^^^^^^^^
void Schedule::DisplayDebug(){ ...
^^^^^^^^^^
Also, don't say using namespace std in a header file (I'd go further and say don't say it anywhere but there isn't universal agreement on that.)
1 Your default constructor does not do anything that the compiler-generated one wouldn't do. You can safely remove it.
I have written this header file (header1.h):
#ifndef HEADER1_H
#define HEADER1_H
class first ;
//int summ(int a , int b) ;
#endif
and this source files (header1.cpp and main.cpp):
#include <iostream>
#include "header1.h"
using namespace std;
class first
{
public:
int a,b,c;
int sum(int a , int b);
};
int first::sum(int a , int b)
{
return a+b;
}
#include <iostream>
#include "header1.h"
using namespace std;
first one;
int main()
{
int j=one.sum(2,4);
cout << j<< endl;
return 0;
}
But when I run this program in codeblocks , I give this Error :
aggregate 'first one' has incomplete type and cannot be defined .
You can't put the class declaration in the .cpp file. You have to put it in the .h file or else it's not visible to the compiler. When main.cpp is compiled the type "first" is class first;. That's not useful at all because this does not tell anything to the compiler (like what size first is or what operations are valid on this type). Move this chunk:
class first
{
public:
int a,b,c;
int sum(int a , int b);
};
from header1.cpp to header1.h and get rid of class first; in header1.h
You need to declare the whole class in a headerfile (that is included every place the class is actually used). Oterhwise, the compiler won't know how to "find" sum in the class (or how much space it should reserve for the class).
If you're using a main function as well, just define the class at the top and define the main later. It is not necessary to explicitly create a separate header file.
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.
I have these two header files and one produces an error if I don't put std:: in front of all string declarations and the other doesn't. I was just wondering what the difference between the two was.
The following will produce an error if the std:: is not in front of the string declarations:
#include <string>
#include <vector>
#pragma once
#ifndef DATABASE_H
#define DATABASE_H
struct Item
{
public:
std::string object;
int numOfColors;
std::string colors;
int sizeSmall;
int sizeLarge;
};
class database
{
private:
void fillDatabase(std::vector<Item>);
public:
void getDatabase(std::vector<Item>);
};
#endif
The following code will not produce an error:
#include <string>
#pragma once
#ifndef GUISTRUCT_H
#define GUISTRUCT_H
struct guiValues
{
public:
string shape;
string color;
int width;
double squareProbability;
double rectangleProbability;
double circleProbability;
string firstMostLikelyObject;
double FMLOprobability;
string secondMostLikelyObject;
double SMLOprobability;
string thirdMostLikelyObject;
double TMLOprobability;
};
#endif
The second file is included after some other that defines
using namespace std;
string is declared in the namespace std. So one needs to use the namespace std to make use of string. it can be done in two ways:
By explicitly mentioning which type(string in this case) you want to include from the std namespace as in case 1, std::string colors
OR
By enabling the entire std namespace, using namespace std; which imports all types from the namespace in your global namespace.(Please note that Doing this in headers is not recommended)
In the second case seems you have included the entire std namespace before the particular include and hence it is not giving an error even without exlpicit mention of std::String