Classes have not been declared but they were included? [duplicate] - c++

This question already has answers here:
Resolve build errors due to circular dependency amongst classes
(12 answers)
Closed 8 years ago.
I have these two classes that need each other and inherited from the same class. Wehn I compile Seller.h, it compiles fine but when I compile Buyer.h I get errors from Seller.h.
So when i compile Buyer.h I get errors such as :
Seller.h:14:16: error: âBuyerâ has not been declared
void addBuyer(Buyer*);
^
Seller.h:15:14: error: âBuyerâ was not declared in this scope
std::vector<Buyer*> getBuyers() const;
Seller.h:20:17: error: âOrderâ has not been declared
void fillOrder(Order*);
^
They are #included but it still says out of scope.
#ifndef SELLER_H
#define SELLER_H
#include "Entity.h"
#include <string>
#include <vector>
#include "Inventory.h"
#include "Buyer.h"
#include "Order.h"
class Seller : public virtual Entity
{
public:
Seller(const std::string &, const std::string &, double=0.0);
virtual~Seller(){}
void addBuyer(Buyer*);
std::vector<Buyer*> getBuyers() const;
void setInventory(Inventory*);
Inventory* getInventory() const;
virtual void list() const override;
virtual void step() override;
void fillOrder(Order*);
private:
Inventory* inv;
std::vector <Buyer*> buyers;
};
#endif
Buyer.h
#ifndef BUYER_H
#define BUYER_H
#include <string>
#include "Entity.h"
#include <queue>
#include "Order.h"
#include "Seller.h"
class Buyer : public virtual Entity
{
public:
Buyer(const std::string &, const std::string &, double =0.0 );
virtual ~Buyer(){}
void addSeller(Seller *);
std::queue <Seller *> getSellers() const;
void addOrder(Order *);
std::queue <Order*> getOrders() const;
virtual void list() const override;
virtual void step() override;
private:
std::queue <Order*> orders;
std::queue <Seller*> sellers;
};
#endif

You have a cyclic dependency between Seller and Buyer. This will never work because the compiler requires the declaration of Seller in order to compile Buyer... yet it also requires the declaration of Buyer to compile Seller.
You can instead forward declare your classes because all you actually use are pointers to these types. For example:
#ifndef SELLER_H
#define SELLER_H
#include "Entity.h"
#include <string>
#include <vector>
#include "Inventory.h"
#include "Order.h"
// forward declaration of Buyer
class Buyer;
class Seller : public virtual Entity
{
public:
Seller(const std::string &, const std::string &, double=0.0);
virtual ~Seller(){}
void addBuyer(Buyer*);
std::vector<Buyer*> getBuyers() const;
void setInventory(Inventory*);
Inventory* getInventory() const;
virtual void list() const override;
virtual void step() override;
void fillOrder(Order*);
private:
Inventory* inv;
std::vector <Buyer*> buyers;
};
#endif
If you had an instance of Buyer as a member of Seller (i.e., Buyer _buyer;), or if any method took/returned an instance of Buyer, you would be forced to change your structure. Since you don't have that problem, a forward declaration will suffice.
As an aside, and admitting that I am not privy to the structure of your program, it is usually a bad sign when one sees so many naked pointers being used in a C++ program. You can store instances. You can use safe pointers (shared_ptr and unique_ptr) depending on your ownership semantics.
For example, addBuyer can easily take a Buyer& instead of a pointer. Now you don't have to worry about invalid pointers. I'm assuming that you add these to your buyers vector... but how are you guaranteeing that these pointers remain valid for the lifetime of a Seller instance? You can't; you're at the mercy of whomever called addBuyer.
Why not just store a std::vector<Buyer> and take a reference in your add method? Is the cost of a copy so prohibitive as to warrant this design? If so, could you not use shared_ptr?

Related

Getting 'undeclared identifier' when using vector of type class

Having trouble understanding why I'm getting an 'undeclared identifier' error when I've made sure to include the header file that has the declaration of the class I'm making a vector of.
#pragma once
#include <vector>
#include "Member.h"
class Party {
private:
std::vector<Member> members;
public:
Party();
int get_party_size();
void add_member(Member new_member);
Member& get_member(int num);
};
Here's "Member.h"
#pragma once
#include <vector>
#include <string>
#include "Party.h"
class Member
{
private:
int hp;
bool is_stunned;
bool is_alive;
public:
Member();
~Member();
int get_hp();
bool get_is_stunned();
bool get_is_alive();
void take_damage(int amt);
void stun();
virtual void turn(std::vector<Party>& parties, int my_party, int my_member_number);
virtual std::string get_class_name();
};
Pretty new to the language, so sure I'm missing something obvious.
You have circular dependency between Member and Party
Remove the line
virtual void turn(
std::vector<Party>& parties,
int my_party,
int my_member_number);
in Member and remove the #include "Party.h" in Member.h
Instead think along the lines that a Party is just a collection of Members so there is no need for an individual Member to know about the container
So after input from #some-programmer-dude you could also solve it by adding a forward declaration in your Member.h instead of including the Party.h
class Party;
class Member { ... }

Troubles with Circular Dependencies between 3 classes and with inheritance

I'm a first-year college student that doesn't know everything about CS yet, so please bear with my newness to it, and this is my first question on here.
For an assignment, we are making faux version of Pokemon Go to practice using polymorphism in c++, and I'm running into some compiler errors. Here are the three files with just a sample of the code in them:
#ifndef EVENT_H
#define EVENT_H
#include <string>
#include "Trainer.h"
class Event{
protected:
std::string title;
public:
Event();
~Event();
virtual void action(Trainer) = 0;
};
#endif
Trainer.h:
#ifndef TRAINER_H
#define TRAINER_H
#include "Pokemon.h"
class Trainer{
private:
Pokemon* pokemon;
int num_pokemon;
public:
Trainer();
~Trainer();
//include accessors and mutators for private variables
};
#endif
Pokemon.h:
#ifndef POKEMON_H
#define POKEMON_H
#include "Event.h"
#include <string>
class Pokemon : public Event{
protected:
std::string type;
std::string name;
public:
Pokemon();
~Pokemon();
virtual bool catch_pokemon() = 0;
};
#endif
The trainer.h file is a parent class for each pokemon type (eg Rock) which just defines a few virtual functions. The error I'm getting is when I'm compiling all of this and I get something that says:
Pokemon.h : 5:30: error: expected class-name befoer '{' token:
class Pokemon : Event {
Pokemon need to be a derived class to an event, so that an event pointer can point in another Location class can point to either a pokemon, pokestop, or cave for the assignment, and I have been looking online for hours and can't figure out what to do. I would appreciate the help! Let me know if you need more info or something because again, this is my first time posting a question.
You need some forward declarations.
In Event.h, you can put class Trainer; instead of #include "Trainer.h". In Trainer.h, you can put class Pokemon; instead of #include "Pokemon.h".
You will probably need to include the appropriate headers in the corresponding source files in order to actually use the other classes. But by avoiding the includes in the header files, you get out of the circular dependency trouble.
Pokemon.h must continue to #include "Event.h", since you're inheriting Event, which requires a complete definition.
Use forward declaration, to tell classes the type they need to use will be defined later. You can use forward declaration in situations where the size is know, pointers and references are always the same size regardless of the type they point to so use them.
#ifndef EVENT_H
#define EVENT_H
#include <string>
class Trainer;
class Event
{
protected:
std::string title;
public:
Event();
virtual ~Event();
virtual void action(Trainer* const trainer) = 0;
};
#endif
then
#ifndef TRAINER_H
#define TRAINER_H
class Pokemon;
class Trainer
{
private:
Pokemon* const pokemon;
int numPokemon;
public:
Trainer();
~Trainer();
};
#endif
then
#ifndef POKEMON_H
#define POKEMON_H
#include "Event.h"
#include <string>
class Pokemon : public Event
{
protected:
std::string type;
std::string name;
public:
Pokemon();
virtual ~Pokemon();
virtual bool catchPokemon() = 0;
};
#endif
when using polymorphism (virtual functions) you must always make the base class destructor virtual too. It is also nice to make the derived classes destructor virtual as well, but it is not required.

Class Pointer as a Data Member of Another Object

just getting an odd error and I'm not entirely sure as to why.
I have 4 files (two headers and two implementations). The issue is inside the headers:
The main file ONLY includes the Station.h, which is why Stations.h is included inside it.
Station.h
#ifndef STATION_H
#define STATION_H
#include "Stations.h"
#include <string>
enum PassType{student, adult};
class Station{
std::string station_name;
unsigned int student_passes;
unsigned int adult_passes;
public:
Station();
void set(const std::string&, unsigned, unsigned);
void update(PassType, int);
unsigned inStock(PassType) const;
const std::string& getName() const;
};
#endif
Stations.h
#ifndef STATIONS_H
#define STATIONS_H
#include "Station.h"
namespace w2{
class Stations{
Station *station;
public:
Stations(char *);
void update() const;
void restock() const;
void report() const;
~Stations();
};
}
#endif
It doesn't know what Station is. I'm getting the following error:
./Stations.h:9:2: error: unknown type name 'Station'; did you mean 'Stations'?
Station *station;
What exactly am I missing here?
You are #includeing Stations.h in Station.h. As a result, the compiler sees class Stations before class Station. In this case, it doesn't appear that Station requires Stations, so you can simply remove the include.
If Station did need to know about Stations, then you'd have to use a forward declaration in one of the headers or the other (and be careful not to use the forward-declared class in a way that required the full definition).
Don't forget to put a semicolon after you declare the Stations class:
class Stations {
Station *station;
};
U need to do the forward declaration.
Remove the #include "Stations.h" from the Station.h
#ifndef STATIONS_H
#define STATIONS_H
#include "Station.h"
namespace w2{
class Station;
class Stations{
Station *station;
public:
Stations(char *);
void update() const;
void restock() const;
void report() const;
~Stations();
};
}
#endif

Class definition expects argument?

I'm designing a class hierarchy that follows a diamond pattern, and I'm trying to debug through about a million errors right now; however, most of them are simple fixes that I should be able to figure out. However, I'm having difficulty understanding the compiler's complaints in this one.
Basically, I start off with a simple Entity class that has two derived classes: Buyer and Seller. A fourth class Retailer, in turn, is descended from both classes - that is, it uses multiple inheritance(and yes, I know what kind of mess that's asking for, unfortunately that's exactly the point of the project).
for reference, the header files for my classes is as follows:
Entity.h
#pragma once
#include <string>
class Entity {
public:
Entity(std::string &, std::string &, double);
/*Accessor methods for private members*/
std::string getName();
std::string getID();
double getBalance();
/*Mutator methods for private members*/
void setName(std::string &);
void setID(std::string &);
void setBalance(double);
/*Additional methods*/
virtual void list();
virtual void step() = 0;
protected:
/*Private members of the entity class*/
std::string name;
std::string id;
double balance;
};
for the Buyer.h file
#pragma once
#include "Entity.h"
#include "Order.h"
#include "Seller.h"
#include <queue>
#include <string>
class Seller;
class Buyer : virtual public Entity {
public:
Buyer(std::string, std:: string, double);
virtual ~Buyer() { }
void addSeller(Seller *);
std::queue<Seller *> getSellers();
void addOrder(Order *);
void list();
void step() override;
protected:
std::queue<Order *> orders;
std::queue<Seller *> sellers;
};
For Seller.h
#pragma once
#include "Entity.h"
#include "Order.h"
#include "Buyer.h"
#include "Inventory.h"
#include <string>
#include <vector>
class Buyer;
class Seller : virtual public Entity {
public:
Seller(std::string, std::string, double);
virtual ~Seller() {}
void addBuyer(Buyer *);
std::vector<Buyer> getBuyers();
void setInventory(Inventory *);
Inventory * getInventory();
void list();
double fillOrder(Order *);
void step();
protected:
Inventory inventory;
std::vector<Buyer *> buyers;
};
And finally for Retailer.h
#pragma once
#include "Buyer.h"
#include "Seller.h"
#include <string>
class Retailer : public Buyer, public Seller {
public:
Retailer(std::string, std::string, double);
virtual ~Retailer() { }
void list();
void step();
};
The majority of the errors I get when trying to compile these files are along the lines of
Buyer.h:9:7: note: candidate expects 1 argument, 0 provided
Seller.h:14:3: note: candidate expects 3 arguments, 0 provided
Which is odd, because for that first line, I shouldn't even have to provide an argument and the second one is the definition of the constructor....
Basically, what I'm failing to understand is what does the compiler mean by a line of code expecting a different number of arguments than were provided? Should I be including default constructors that use no arguments? Is there something wrong with the way they're declared? I can also post the code for my .cpp files if necessary, although they don't seem to be mentioned a lot by the compiler error reports.
It means that the compiler is considering that function for overload resolution, but it's not a match because of differing number of arguments.

Inaccessible object when compiling code

I want to compile the Rigi source code but I get some error while compiling:
adt/object.h: At global scope:
adt/object.h:35:18: error: ‘class RigiObject RigiObject::RigiObject’ is inaccessible
adt/chararray.h:51:13: error: within this context
make: *** [cl_arcflags.o] Error 1
Here our two files.
object.h:
#ifndef OBJECTH
#define OBJECTH 1
#include <stdio.h>
#ifndef STREAM_H
#include <iostream>
#endif
#ifndef __STRING_H
#include <string.h>
#endif
#ifndef __STDLIB_H
#include <stdlib.h>
#endif
#ifndef _CCHEADER_H_
#include "CCheader.h"
#endif
extern char* indent_line(int);
class RigiObject;
typedef RigiObject* ObjectPtr;
#define Oberr(a) fprintf(stderr,"ERROR :: Generic Object Routine Called :: %s\n","a");
class RigiObject {
public:
RigiObject() {/*Oberr(RigiObject)*/;}
~RigiObject() {/*Oberr(~RigiObject)*/;}
// Routines that are really described by the Derived Classes
virtual int Printout(int) const
{Oberr(printout); return (int) 0;}
virtual unsigned int Hash() const
{Oberr(hash); return (unsigned int) 0; }
virtual RigiBool isEqual(void* a) const
{Oberr(isEqual); a = NIL;
(void) abort();
return (RigiBool) RigiFalse;}
virtual void Delete_class(ObjectPtr)
{Oberr(delete_type);}
virtual void* Create_class();
virtual void* Duplicate_class();
};
#endif
and chararray.h:
#ifndef CHARARRAYH
#define CHARARRAYH
#ifndef ARRAYOBIDH
#include "array.h"
#endif
#ifndef CHARTYPEH
#include "chartype.h"
#endif
class CharArray;
typedef CharArray* CharArrayPtr;
class CharArray : public Array {
int slot;
public:
// Routines to initialize and destroy the class.
CharArray(unsigned int size = CLTN_DEFAULT_CAPACITY);
CharArray(const CharArray&);
~CharArray();
// Functions that are Required to Use this Class as an Object
// .... all routines the same as in Class Array.......
// Routines that are required by a Collection class and derived classes
// of Collections. [See Array Class for these routines.]
virtual unsigned int size() const {return slot;}
// .... all routines the same as in Class Array.......
// Routines specific to this class
void operator=(const CharArray&);
RigiBool operator==(const CharArray&) const;
void Create(char*);
void Create(char*,int);
void Create(int, char*);
void Add(char*);
void Add(CharType&);
void Addob(RigiObject& ob)
{Array::Add(slot++,&ob);}
void Append(char*);
char* Concat(char);
int FindIndex(char*);
char* Remove()
{return ((CharTypePtr)Array::Remove(--slot))->string();}
ObjectPtr Pop()
{return (Array::Remove(--slot));}
ObjectPtr Look(int i)
{return (Array::At(i));}
void Empty();
virtual unsigned int Size() const
{return slot;}
char* Peek();
char* At(int);
};
#endif
What's wrong with the code?
Assuming that the type RigiBool in the declaration RigiBool operator==(const CharArray&) const; is not defined in one of the headers "array.h" "chartype.h" I think you should include the header containing definition of the type, and just to be sure the "object.h" too.
For cases where a header file uses values of class type variables (not pointers and references) it is recommended to include the headers that contain the class definition. Otherwise a simple forward declaration should be enough.
The types RigiBool, RigiObject and ObjPtr are not available in chararray.h: you need to include object.h (plus whatever else defines RigiBool if CCHeader.h doesn't) -- similarly for RigiBool and RigiFalse in object.h
// somewhere at the top of chararray.h
#include "object.h"
Note: if you define virtual member functions in RigiObject, you should declare the destructor virtual as well
Note: You already have include guards in the #included headers, no need to put them around the #include directives -- doing otherwise indicates (falsely in your case) that you are doing conditional compiling
//chararray.h
#ifndef CHARARRAYH
#define CHARARRAYH
#include "array.h"
#include "chartype.h"
...
//object.h
#ifndef OBJECTH
#define OBJECTH
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include "CCheader.h"
...
It's hard to say from the little information but I would assume RigiBool is a derived class of RigiObject? When you now reference RigiBool in chararray.h it has to know the RigiObject base class but the RigiObject also needs to know about RigiBool. So you can't declare the base class without knowing the derived RigiBool. Try if forward declaring RigiBool in object.h helps to break the cycle.