C++ Undeclared Identifier (but it is declared?) - c++

I'm pretty sure I've included the qanda class, but when I try to declare a vector that contains it or a class of that type I get an error saying that qanda is undefined. Any idea what the problem might be?
bot_manager_item.h
#pragma once
#include "../bot_packet/bot_packet.h"
#include <vector>
class bot_manager_item;
#include "qanda.h"
#include "bot_manager.h"
class bot_manager_item
{
public:
bot_manager_item(bot_manager* mngr, const char* name, const char* work_dir);
~bot_manager_item();
bool startup();
void cleanup();
void on_push_event(bot_exchange_format f);
bool disable;
private:
void apply_changes();
bot_manager *_mngr;
std::string _name;
std::string _work_dir;
std::string _message;
std::string _message_copy;
std::vector<qanda> games;
qanda test;
char _config_full_path[2600];
};
qanda.h
#ifndef Q_AND_A
#define Q_AND_A
#include "users.h"
#include "..\bot_packet\bot_packet.h"
#include "bot_manager.h"
#include <string>
#include <algorithm>
#include <map>
#include <vector>
#include <fstream>
class qanda
{
public:
qanda(bot_manager * manager, std::string name, std::string directory);
~qanda(){};
void room_message(std::string username, std::string user_message);
void timer_tick();
private:
// data members
std::string question;
std::string answer;
std::string directory;
std::string command_prefix;
std::string name;
Users users;
std::map <std::string, std::string> questions_and_answers;
int time_per_question; // seconds
int time_between_questions; // seconds
int timer; // milliseconds
bool is_delayed;
bool is_playing;
bot_manager * manager;
// functions
void new_question();
void send_message(std::string msg);
void announce_question();
void load_questions();
};
#endif
Solved: I ended up refactoring the code in such a way as to avoid the use of bot_manager within the qanda class.

I suspect a circular #include problem. Is it possible qanda.h indirectly includes bot_manager_item.h?
It looks like you may be able to reduce header dependencies by using a forward declaration
class bot_manager;
instead of #include "bot_manager.h" in one or both of your posted header files.

Related

Using friend function correctly across multiple Classes in C++

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.

Issues with function implementation in multiple header files

I am currently working on a project with several other people. We originally had one header file with class and method declarations and one .cpp file with implementation/main. We decided to try and move the function implementation to the header files so we could all work on different features at the same time without producing as many merge conflicts in git.
When I compile the code, I get "undeclared identifier" errors and others that follow, leading me to the conclusion that something is wrong with the way my headers are set up. The code is long, so I'll try to provide a relevant example:
(Assignment.h and Student.h contain classes in a similar setup)
Instructor.h:
#pragma once
#include "Assignment.h"
#include "Student.h"
#include "Course.h"
#include <string>
#include <vector>
#include <fstream>
#include <iostream>
#include <sstream>
#include <algorithm>
using namespace std;
class Instructor {
private:
std::string instructorName;
std::vector<Course*> courseList;
public:
Course *currentCourse;
Instructor();
Instructor(std::string name);
void setName(std::string name);
std::string getName();
void firstTimeInstructor();
void addCourse();
void addCourse(std::string name);
void removeCourse();
void mainMenu();
void init();
};
... implementation for Instructor methods...
Course.h:
#pragma once
#include "Assignment.h"
#include "Student.h"
#include "Instructor.h"
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
using namespace std;
class Course {
private:
std::string courseName;
std::vector<Student*> studentList;
std::vector<Assignment*> assignmentList;
public:
Course(std::string name);
void setCourseName(std::string name);
std::string getCourseName();
void showCourseOptions();
void addStudent();
void addStudent(std::string first, std::string last);
void addAssignment();
void addAssignment(std::string name, double points);
void print();
void courseMenu();
};
...implementation for Course methods...
First error: instructor.h(17): error C2065: 'Course': undeclared identifier
(Similar ones follow: Student, Assignment, etc.)
I was studying this post for a while, but I wasn't really able to find a definitive answer and I wasn't sure if it even applied to my situation.
I know some of this (such as the using namespace std or even declaring functions in the header) may be bad practice, but we're all a bit new to this so any guidance on the subject would be appreciated.

Object was not declared in scope (std::map)

I have a class with a map called students where I would like to store instances of another class. I get the following error message:
‘Student’ was not declared in this scope
std::map<int, Student> students;
Here is the relevant part of my code:
APP.H
#include <iostream>
#include <string>
#include <map>
#include "student.h"
class App
{
public:
void AddStudent();
protected:
std::string SName;
std::string SEmail;
std::map<int, Student> students;
};
APP.CPP
#include <string>
#include <iostream>
#include "app.h"
#include "student.h"
void App::AddStudent()
{
std::cin >> SName;
std::cin >> SEmail;
Student Stu(SName, SEmail);
students.insert(std::make_pair(someID, Stu));
}
STUDENT.H
#include <string>
#include <iostream>
#include "app.h"
#include "test.h"
class Student
{
public:
Student() { }
Student(std::string studentName, std::string studentEmail);
int studentId;
std::string GetStudentName() const;
std::string GetStudentEmail() const;
void SetStudentName(std::string sn);
void SetStudentEmail(std::string se);
private:
static int tempId;
std::string studentName;
std::string studentEmail;
};
If I copy my map to main, I don't receive this error, but then I can't access it when I try to insert the instance. I'd rather not have this map in main.
student.h includes app.h, but app.h includes student.h.
In your case, you can just remove the #include "app.h" from student.h, because it is not needed.
Making my comment as an answer:
Do the following two things:
No need to include student.h in app.cpp, it already gets it via the inclusion of app.h
Do not include app.h in student.h

undefined reference to vtable when using interface

I've looked around, and I can't quite figure out where I'm going wrong, as I seem to be following the correct convention when using interfaces, but perhaps I'm overlooking something. The exact error I'm getting is:
undefined reference to `vtable for Icommand'
I've only just begun to seperate my classes and class declarations into separate header files, so perhaps I'm missing a preprocessor directive somewhere.
main.cpp:
#include <iostream>
#include <string>
#include <cstdlib>
#include "Icommand.h"
#include "Command.h"
using namespace std;
void pause();
int main(){
Icommand *run = new Command("TEST");
cout << run->getCommand() << endl;
delete run;
pause();
}
void pause(){
cin.clear();
cin.ignore(cin.rdbuf()->in_avail());
cin.get();
}
Icommand.h:
#ifndef ICOMMAND_H
#define ICOMMAND_H
#include <string>
#include <vector>
class Icommand
{
private:
public:
Icommand(){}
virtual ~Icommand(){}
virtual bool run(std::string object1) = 0;
virtual bool run(std::string object1, std::string object2) = 0;
virtual std::string getCommand() const;
};
#endif // ICOMMAND_H
Command.h:
#ifndef COMMAND_H
#define COMMAND_H
#include <string>
#include <vector>
#include "Icommand.h"
class Command : public Icommand {
private:
std::string command;
std::vector<std::string> synonymns;
Command(); // private so class much be instantiated with a command
public:
Command(std::string command) : command(command){}
~Command(){}
bool run(std::string object1);
bool run(std::string object1, std::string object2);
std::string getCommand() const;
};
#endif // COMMAND_H
Command.cpp:
#include <string>
#include <vector>
#include "Command.h"
bool Command::run(std::string object1){
return false;
}
bool Command::run(std::string object1, std::string object2){
return false;
}
std::string Command::getCommand() const {return command;}
In Icommand.h, replace
virtual std::string getCommand() const;
with
virtual std::string getCommand() const = 0;
to make it pure virtual. Then the compiler can generate a vtable for Icommand. Alternatively, implement Icommand::getCommand.

Classes as parameters error

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.