I am trying to move from using structs to using classes, and I have a few questions with my - not fully complete, but enough to illustrate my queries - code (thank you in advance for clarifying these):
I am having problems with creating a constructor that takes in arguments, specifically the line in the header file that I have currently left as neighborAtt(int neighbor_id, int att_1, int att_2);.
When using neighborAtt as a struct, I could do it easily as neighborAttributes currentNode(neighborID, att1, att2);. What is the class-equivalent?
In the .cpp file, I know that I need to define the constructor as neighborAtt::neighborAtt().
Do I need to this with the functions (i.e. include neighborAtt::) or is what I've done accurate?
This is my header file:
#if !def connectivity_H
#define connectivity_H
#include <iostream>
#include <vector>
#include <list>
#include <string>
#include <sstream>
#include <fstream>
class listAtt;
class vecListAtt;
class neighborAtt //contains the neighbour and associated attributes of a node
{
public:
neighborAtt();
neighborAtt(int neighbor_id, int att_1, int att_2);
vecListAtt connFrFile(int file_ext);
vecListAtt makeList(std::vector<std::list<neighborAtt>> nodeAndInfo, int nodeID, neighborAtt neighAndAtt);
neighborAtt getAtt(std::string currentLine);
private:
int neighborID;
int attribute1;
int attribute2;
};
typedef std::list<neighborAtt> listAtt;
typedef std::vector<listAtt> vecListAtt;
#endif
and the .cpp file:
#include "stdafx.h"
#include "connectivity.h"
neighborAtt::neighborAtt(): neighborID(0), attribute1(0), attribute2(0) {}
//neighborAtt::neighborAtt constructor with arguments
vecListAtt connFrFile(int file_ext)
{
//code
}
neighborAtt getAtt(std::string line)
{
//code
}
For the second constructor (one with the arguments) you do just the same as for one without them. Or did I get the question wrong? It'd be like:
neighborAtt::neighborAtt(int neighbor_id, int att_1, int att_2)
: neighborID(neighbor_id),
attribute1(att_1),
attribute2(att_2)
{
}
And for the methods you must go the same way:
vecListAtt neighborAtt::connFrFile(int file_ext)
{
//code
}
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 will start this out by saying c++ is my first programming language and I am a beginner at best. And I am sure this has some sort of obvious answer.
But for some reason this simple program with a single custom class is returning very odd values from the Get functions that are calling the private members of the one custom class.
The program is separated into three file as follows.
#include <iostream>
#include <cmath>
#include <string>
#include <cctype>
#include "Shapes.h"
using namespace std;
int main ()
{
double test=20.0;
Cube D(test);
cout<< D.GetSA()<<endl<<D.GetSide();
return 0;
}
then as header files for the one Classes called Shapes.h
#include <iostream>
#include <cmath>
#include <string>
#include <cctype>
using namespace std;
class Cube
{
public:
Cube();
Cube(double);
double GetSA() const;
double GetSide() const;
private:
double SA;
double V;
double Side;
};
And another file Called Shapes.cpp that contains the Constructor.
#include <iostream>
#include <cmath>
#include <string>
#include <cctype>
#include "Shapes.h"
Cube::Cube()
{
V=0.0;
SA=0.0;
Side=0.0
}
Cube::Cube(double Side2)
{
Side=Side2;
}
double Cube::GetSA() const
{
return SA;
}
double Cube::GetSide() const
{
return Side;
}
for some reason when this program is run it returns a value of 6.95293e-310 for the GetSA accessor function and returns a value of 200 for the side function.
Any ideas on why this is happening and how to fix it?
Try invoking the default constructor. It seems to initialize the data members correctly. Your parameterized constructor is only initializing the Side data member, and not any other data members.
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.
error C2071: 'Lexicon::list' : illegal storage class
I have a class that reads a bunch of strings into memory and then provides functions that allow applying operations on those strings and their relationships. As part of this I'd like to have a shared memory between the main.cpp where some of the operations are initiated and the class where the operations are completed. For this, in a previous post, it was suggested to use an extern type. But, now there is an error. How do I resolve this error and have a memory space shared by several classes?
in lexicon.h
#ifndef _lexicon_h
#define _lexicon_h
#include <string>
#include <vector>
using namespace std;
class Lexicon {
public:
Lexicon();
~Lexicon();
extern vector<vector<string>> list;
void buildVectorFromFile(string filename, vector<vector<string>> &list, int v, int h);
private:
struct charT { char letter; nodeT *next;};
};
#endif
in main.cpp
#include <string>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <vector>
#include "lexicon.h"
void buildVectorFromFileHelper (Lexicon & lex)
{
vector<vector<string>> list;
lex.buildVectorFromFile("ASCII.csv", list, 200, 2); //build 2x200 vector list
}
Ok, I missunderstood your previous question (this is what happens when you don't post full code). Inside a class, extern is not used:
in lexicon.h
#ifndef _lexicon_h
#define _lexicon_h
#include <string>
#include <vector>
using namespace std;
class Lexicon {
public:
Lexicon();
~Lexicon();
vector<vector<string>> list;
private:
struct charT { char letter; nodeT *next;};
};
#endif
in main.cpp
#include <string>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <vector>
#include "lexicon.h"
void buildVectorFromFileHelper (Lexicon & lex)
{
vector<vector<string>> list;
lex.buildVectorFromFile("ASCII.csv", list, 200, 2); //build 2x200 vector list
}
The problem here is that Lexicon doesn't have the method buildVectorFromFile, so how are you calling lex.buildVectorFromFile("ASCII.csv", list, 200, 2);?
To share the same vector, if it's a member, make it static:
class Lexicon {
public:
Lexicon();
~Lexicon();
static vector<vector<string>> list;
private:
struct charT { char letter; nodeT *next;};
};
In lexicon.cpp:
vector<vector<string>> Lexicon::list;
The rules of an extern memory is explained here in this daniweb thread; the comment there is that yes, this should be simple but it is somehow not intuitive. The gist is that the memory is globally declared with the extern prefix in .cpp file A and then to reuse the memory in cpp B, globally declare it again in .cpp file B.
I think Luchian_Grigore and #jahhaj were getting there but we had either just not found the words for me to understand or they were still finding the words to explain.
In Weapon.h, when I try and take a class 'Entity*' as a parameter, it says "Syntax error: identifier 'Entity'" when I compile. Additionally when I roll over the text 'target', Visual C++ Express 2010 gives me the text " *target". The Entity class is fine and I'm pretty sure it's included correctly.
(I won't post Player.h as it's unnecessary - see Library.h - but it has a header guard and includes Entity.h)
Library.h:
#ifndef _LIBRARY_
#define _LIBRARY_
#include <iostream>
#include <string>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <cstdarg>
#include <vector>
#include <ctime>
#include <cmath>
#include <cstdlib>
#include <map>
#include <exception>
#include <sstream>
//file includes
#include "Globals.h"
#include "Player.h"
#include "Exception.h"
#include "Weapon.h"
#include "Armour.h"
#include "Consumable.h"
//prototypes that require "Library.h"
bool Poglathon(std::vector<std::string>& text,Player *player);
bool PoglathonTown(std::vector<std::string>& text,Player *player);
std::map<std::string,Weapon*> init_weapons(void);
std::map<std::string,Armour*> init_armour(void);
std::map<std::string,Consumable*> init_consumables(void);
#endif //__LIBRARY__
Weapon.h:
#ifndef _WEAPON_H_
#define _WEAPON_H_
#include "Shopable.h"
class Weapon : public Shopable{
private:
int Damage;
public:
Weapon(int c,int d,std::string n) : Shopable(c,n),Damage(d){}
std::string getDesc() const{
return getName()+"\t"+tostring(Damage)+"\t"+tostring(Cost);
}
int getDamage() const{return Damage;}
int DamageTarget(Entity* target){
int DamageDealt = 0;
//do damage algorithm things here
return DamageDealt;
}
};
#endif
Shopable.h:
#ifndef _SHOPABLE_H_
#define _SHOPABLE_H_
#include "Library.h"
class Shopable{
protected:
std::string Name;
int Cost;
std::string Description;
public:
Shopable(int c, std::string n):Cost(c),Name(n){}
std::string getName() const{return Name;}
int getCost() const {return Cost;}
virtual std::string getDesc() const = 0;
};
#endif
Entity.h:
#ifndef _ENTITY_
#define _ENTITY_
#include "Library.h"
#include "Weapon.h"
#include "Armour.h"
#include "Consumable.h"
class Entity{
public:
void printStats() const;
void heal(double health);
std::string name;
protected:
//player stats
double str; //strength
double wis; //wisdom
double ref; //reflex
double hp; //health points
double maxHp; //maximum health points
double i; //initiative
double inte; //intelligence
double c; //courage
int gold; //gold
int xp; //experience
int ap; //armour points
int wd; //weapon damage
int lvl; //level
int sp; //skill points
Weapon* weapon;//weapon
Armour* cArmour;//current armour
};
#endif
In C++, classes must be declared before they are referenced. You are #include-ing Weapon.h in Entity.h, but at that point, the compiler doesn't know about the existence of class Entity.
You will either need to change the order in which things are declared, or add a forward declaration "above" class Weapon. It can simply be:
class Entity;
That tells the compiler that there is such a name as Entity. However, it doesn't tell it anything about what members it has, so you can't actually do anything with it, other than declare variables of Entity * and Entity &, and pass them around.
Your headers include each other because your classes refer to each other. (But your compiler doesn't suffer from a stackoverflow because of your include guards - that's a good thing!)
You should arrange your header files hierarchically, ie there are files at the 'top' which #include nothing and files 'below' which include some of the top ones and so-on down the hierarchy. But at no point should there be 'loops'.
In order to break your loops in your code, any classes that refer to each other should forward declare any mutual dependencies and only refer to dependency names and not their members.
e.g.
Entity.h
class Weapon;
class Entity{
...
Weapon* weapon;
};
Weapon.h
class Entity;
class Weapon{
...
int DamageTarget(Entity* target);
};
Notice how Weapon.h only refers to Entity*.
You will need to define int Weapon::DamageTarget(Entity* target) in Weapon.cpp
#include <entity.h>
Or forward-declare only in the header
class Entity;
This makes compilation a bit faster (you still need to include it to use in the implementation).
Weapon.h doesn't #include Entity.h, or anything that recursively includes it. Therefore, it doesn't know about the class Entity.