I am new to C++.In order to learn this, I am making a phonebook application which uses C++ concepts and functionalities. I have made two classes, phonebook and features; the phonebook class uses all functions of features, and the features class uses functions of phonebook.
But, when I am trying to pass a features class object to phonebook functions as an argument, the compiler gives an error that "features is not a type".
Why this error is coming – features is a class here not a datatype? How can I resolve this issue?
Please see below code:
#include<stdlib.h>
#include<string.h>
#include<iostream>
#include<fstream>
#include<windows.h>
#include<iomanip>
#include<regex>
#define ADD_CONTACT 1
#define DELETE_CONTACT 2
#define EDIT_CONTACT 3
#define SHOW_CONTACT 4
#define DISPLAY_CONTACTS 5
#define SETTINGS 6
#define EXIT_MAIN 7
using namespace std;
class features;
//phone book page
class phonebook
{
//details of contact:
//mandatory details to store a contact
string first_name;
string last_name;
bool name_order;
string mobile_num;
string work_num;
string home_num;
//additional details for a contact
string company_name;
string job_title;
string email;
string location;
string dob;
bool favorite_flag;
bool friend_flag;
bool family_flag;
bool office_flag;
bool work_num_flag;
bool home_num_flag;
bool mobile_num_flag;
//flags of details whether present or not:
bool company_name_present=0;
bool job_title_present=0;
bool email_present=0;
bool address_present;
bool dob_present=0;
bool relation_present;
bool location_present=0;
//number of contact numbers present for each contact
//kind of number either work or home or mobile or telephone_home or telephone_office
int num_kind;
//link for linked list
phonebook* link;
//bool allocate_mem_to(phonebook* &);
bool check_number_valid(string &);
bool check_email_valid(string &);
void reverse_linked_list(phonebook* &);
void add_in_sorted_order(phonebook* &,phonebook* &,bool,bool);
void print_all_the_details(phonebook* &);
friend void operator>>(istream&,phonebook*&);
friend void operator<<(ostream&,phonebook*&);
public:
phonebook(){
favorite_flag=0;
friend_flag=0;
family_flag=0;
office_flag=0;
mobile_num_flag=0;
work_num_flag=0;
home_num_flag=0;
company_name_present=0;
job_title_present=0;
email_present=0;
location_present=0;
dob_present=0;
relation_present=0;
name_order=0;
link=NULL;
}
~phonebook(){}
friend class features;
void add_contact(phonebook* &,features obj);
void delete_contact(phonebook* &,features obj);
void edit_contact(phonebook* &,features obj);
void show_contact(phonebook* &,features obj);
void display_contacts(phonebook* &,features obj);
void features();
bool phonebook_login_operations();
};
class features
{
bool sort_flag;
bool name_order_flag;
bool friends_display;
bool family_display;
bool office_display;
bool all_contacts_display;
bool only_favourites;
public:
friend class phonebook;
features();
~features()
{
}
void add_to_favourites(phonebook* &);
void contacts_to_display();
void sort_by();
void name_order();
void print_main_admin_menu();
};
void phonebook::add_contact(phonebook* &head,features obj)//Here complier gives error"features is not type"
{
phonebook *temp_obj=NULL,*read_obj=NULL,*traverse_pointer=NULL;
temp_obj=new phonebook;
cin>>temp_obj;
bool sort_flag_1=0;
bool name_order_flag_1=0;
ifstream file_in;
file_in.open("phonebook_contacts.txt");
if(file_in)
{
if(head==NULL)
{
if(obj->sort_flag == false)
sort_flag_1=0;
else
sort_flag_1=1;
if(obj->name_order_flag == false)
name_order_flag_1=0;
else
name_order_flag_1=1;
while(file_in)
{
read_obj=new phonebook;
file_in.read((char*)read_obj,sizeof(*read_obj));
add_in_sorted_order(head,read_obj,sort_flag_1,name_order_flag_1);
}
}
add_in_sorted_order(head,temp_obj,sort_flag_1,name_order_flag_1);
file_in.close();
ofstream file_in_out;
file_in_out.open("phonebook_contacts.txt");
for(traverse_pointer=head;traverse_pointer;traverse_pointer=traverse_pointer->link)
file_in_out.write((char*)traverse_pointer,sizeof(*traverse_pointer));
file_in_out.close();
}
else
{
ofstream file_out;
file_out.open("phonebook_contacts.txt");
file_out.write((char*)temp_obj,sizeof(temp_obj));
file_out.close();
}
}
features is a class here not a datatype.
Are you sure about that? You may know what you mean, but the compiler is confused … because of this line near the end of the definition of the phonebook class:
void features();
So, to the compiler, the name, features could refer to either the class of that name or to the member function of the same name. Adding the class tag will inform the compiler that you do, indeed, mean the class (and not the member function – which is 'in scope' here, because add_contact is a member of phonebook)1.
Alternatively, as you don't appear (in the code you've shown) to ever actually use the void features() function, just comment that out (or remove it).
Also, with either of those corrections applied, you will then have errors where you use code like obj->sort_flag and obj->name_order_flag inside add_contact. The obj parameter is not declared as a pointer: so, either make it one (i.e. void phonebook::add_contact(phonebook*& head, features* obj), in both the definition and the in-class declaration, or change the two -> operators to .. (The former is probably the best option, though that will ultimately depend on your use-case.)
1 Actually, the compiler isn't really "confused" at all: it is obliged to interpret features as referring to the member function, because the argument is inside the phonebook class scope. As an alternative to using the class tag before features, you could also add the global scope-resolution operator, ::, like this:
void phonebook::add_contact(phonebook*& head, class features obj)
or:
void phonebook::add_contact(phonebook*& head, ::features obj)
Related
Error message:
Link to full program
class AddressBook
{
private:
char firstname[20];
char lastname[20];
char no[15];
class adrs
{
public:
char postal[100];
char pincode[7];
friend void say();
friend void Add();
friend void Edit();
friend void View(int);
}address;
char dob[11];
char email[50];
public:
friend void say();
void sort(AddressBook []);
void NumberSort(AddressBook []);
void Add(void);
void Delete(AddressBook [], int pos);
void Edit();
void LinearSearch(AddressBook [], char a[]);
friend void ViewAll();
void View(int);
void FetchContact();
};
This is the declaration of a class for a contact-book program.
void sort(AddressBook []);
void NumberSort(AddressBook []);
void Delete(AddressBook [], int pos);
void LinearSearch(AddressBook [], char a[]);
These lines in the above declaration shows up as an error in TurboC++ compiler. Can anyone tell me why?
In C++ when an array is passed as an argument, its initial address is passed to formal parameter. With the help of this technique the code can be written as follows
void sort(AddressBook*);
void NumberSort(AddressBook*);
void Delete(AddressBook*, int pos);
void LinearSearch(AddressBook*, char a[]);
I have implemented the same thing for my problem and it just worked.
As you were not able to produce minimal example, I did it for you:
class AddressBook
{
void sort(AddressBook[]);
};
This declaration compiles fine on a modern compiler but not on Turbo C++.
You can call this a compiler bug.
There are two options:
you rethink your program and write it another way
you use a modern C++ compiler
Changing school would be another valuable option.
I'm still fairly new to inheritance and polymorphism, so forgive me. I'm writing a group of derived classes using Scite editor in Linux, and am receiving a compile error stating that my value constructor implementation doesn't match the prototype in the header file.
powerseller.cpp:9:1: error: prototype for \u2018PowerSeller::PowerSeller(std::string, std::string, std::string, std::string, std::string, std::string, std::string, std::string, std::string, std::string)\u2019 does not match any in class \u2018PowerSeller\u2019
powerseller.h:15:3: error: candidates are: PowerSeller::PowerSeller(const PowerSeller&)
powerseller.h:13:3: error: PowerSeller::PowerSeller(std::string, std::string)
powerseller.cpp:7:1: error: PowerSeller::PowerSeller()
Here's my header file. The value constructor is the one throwing the error.
#include "seller.h"
#ifndef POWERSELLER_H
#define POWERSELLER_H
using namespace std;
class PowerSeller : public Seller
{
public:
//constructors & destructors
PowerSeller();
PowerSeller(string fName, string lName, string id, string email, string loc, string date, string numOfStars, string numOfItems, string webAddress, string yearItems);
PowerSeller(const PowerSeller& other);
~PowerSeller();
//member functions
void setWebsite(string webAddress);
void setYearItems(string yearItems);
virtual void print();
virtual void read();
//overloaded operators
bool operator ==(const PowerSeller& rhs);
PowerSeller & operator =(const PowerSeller& rhs);
//overloaded ostream
friend ostream & operator <<(ostream& os, const PowerSeller& rhs);
protected:
string website, items;
};
#endif
Here's the implementation
include "powerseller.h"
#include <iostream>
using namespace std;
PowerSeller::PowerSeller(){}
PowerSeller::PowerSeller(string fName, string lName, string id, string email, string loc, string date, string numOfStars, string numOfItems, string webAddress, string yearItems): Seller(fName, lName, id, email, loc, date, numOfStars, numOfItems){
website = webAddress;
items = yearItems;
}
PowerSeller::PowerSeller(const PowerSeller& other):Seller(other){
website= other.website;
items = other.items;
}
PowerSeller::~PowerSeller(){
website = " ";
items = " ";
}
My ultimate question is: Why is the compiler still showing that PowerSeller's value constructor only accepts two string arguments when I've altered it in the file to match the implementation?
This question already has an answer here:
g++ error: ‘vec’ does not name a type [duplicate]
(1 answer)
Closed 8 years ago.
Ok so I am trying to map some of my member functions in the .h file this is to be able to use the map when I implement the code. However, after hours I have gotten nowhere so I would like suggestions or if anyone knows how to implement this. For reference these are the errors.
./Assembler.h:51:2: error: C++ requires a type specifier for all declarations
functions["load"] = load;
^~~~~~~~~
./Assembler.h:51:12: error: size of array has non-integer type 'const char [5]'
functions["load"] = load;
^~~~~~
./Assembler.h:51:2: error: duplicate member 'functions'
functions["load"] = load;
^
As for my header file it with the problem coming from the map:
#include <vector>
#include <iostream>
#include <map>
#include <string>
#include <fstream>
using namespace std;
class Assembler {
public:
Assembler(string filename);//Argument will be passed from the os.cpp file
void parse();// Will go through the a file to output the .o file
void load();
void loadi();
void store();
void add();
void addi();
void addc();
void addci();
void sub();
void subi();
void subc();
void subci();
void ander();
void andi();
void xorer();
void xori();
void negate();
void shl();
void shla();
void shr();
void shra();
void compr();
void compri();
void getstat();
void putstat();
void jump();
void jumpl();
void jumpe();
void jumpg();
void call();
void ret();
void read();
void write();
void halt();
void noop();
private:
typedef void (*function)();
map<string, function> functions;
functions["load"] = load;
fstream in, out; //One will be the .s file while the other will be the .o file
string opcode;
int rd, rs, constant, addr, machcode; //Different parts of the instruction
};
Any help or suggestions would be appreciated. Thanks
Only static const integral data members can be initialized within a class. You probably need to move functions["load"] = load; to a function's definition.
And also, you need to change them to:
typedef void (Assembler::*function)();
...
functions["load"] = &Assembler::load;
Within C++ class declaration, you cannot have member initialiser or executable statement, Have this one
functions["load"] = load;
within constructor
Take a look at your class declaration: everything's compiling fine except
functions["load"] = load;
This is an assignment and initializes the functions map with something. That is not allowed in the declaration which is a "contract" (in the case of an interface) or "explanation" of how your class is composed and what methods/members has.
The right spot to put such an initialization is in your constructor's definition (i.e. in the part of the code that actually contains the code of your methods, specifically when the object gets created if you intend to initialize stuff.. i.e. the constructor).
I know there are a couple other questions on this specific question, but nothing that I can find on it seems to work, so I'm posting my specific code.
Here is the code:
#ifndef __MEMORY_TRACKER_H__
#define __MEMORY_TRACKER_H__
#include <unordered_map>
namespace cige
{
namespace memory
{
class CIGE_API MemoryTracker
{
protected:
typedef struct AllocRecord
{
size_t bytes;
std::string filename;
size_t line;
std::string func;
AllocRecord() :
bytes(0), line(0)
{ }
AllocRecord(size_t sz, const char* file, size_t ln, const char* fun) :
bytes(sz), line(ln)
{
if (file)
filename = file;
if (fun)
func = fun;
}
} AllocRecord;
std::string m_leakFileName;
bool m_dumpToConsole;
typedef std::unordered_map<void*, AllocRecord> AllocMap;
AllocMap m_allocationMap;
size_t m_totalAllocations;
bool m_recordEnable;
protected:
void reportLeaks();
MemoryTracker() :
m_leakFileName("CIGEMemory.log"), m_dumpToConsole(true), m_totalAllocations(0), m_recordEnable(true)
{ }
public:
void setReportFileName(const std::string& name)
{
m_leakFileName = name;
}
const std::string& getReportFileName() const
{
return m_leakFileName;
}
void setReportToConsoleOutput(bool b)
{
m_dumpToConsole = b;
}
bool getReportToConsoleOutput() const
{
return m_dumpToConsole;
}
void setRecordEnable(bool b)
{
m_recordEnable = b;
}
bool getRecordEnable() const
{
return m_recordEnable;
}
size_t getTotalMemoryAllocated() const
{
return m_totalAllocations;
}
void _recordAlloc(void* ptr, size_t sz, const char* file = nullptr, size_t ln = 0, const char* fun = nullptr);
void _recordDealloc(void* ptr);
~MemoryTracker()
{
reportLeaks();
}
static MemoryTracker& get();
};
}
}
#endif // __MEMORY_TRACKER_H__
I'm getting: variable 'cige::memory::CIGE_API cige::memory::MemoryTracker' has initializer but incomplete type at the line with the class declaration. I've looked all over and I cant find any answers that have fixed this issue.
I'm also having the error expected '}' or ',' or ';' before 'protected' at the line with protected, right above the struct.
Any help with either of these two errors would be appreciated.
EDIT: CIGE_API is defined in a separate file (which is included), as __declspec(dllexport).
EDIT2: I fixed my problem (see the answer below). It was basically just Code::Blocks derping out pretty bad.
Looks like CIGE_API is not defined. So compiler try to resolve it like variable declaration class Type Variable {initializer-list}, where Type is CIGE_API and Variable is MemoryTracker.
In other words, syntactically you're predeclaring CIGE_API type and creating variable of this type instead of defining a class.
The definition
class CIGE_API MemoryTracker { ... };
is not valid C++. I guess CIGE_API is a macro defined to an implementation specific extension, but you didn't include the corresponding header which defines that macro.
Ok I ended up fixing my own problem. Code::Blocks wasn't properly finding files that were in my project (about the third time this has happened).
In entirely unrelated news, does anyone know another cross-platform IDE that works well for C++? (I already know about Eclipse).
I'm getting this linker error. I know a way around it, but it's bugging me because another part of the project's linking fine and it's designed almost identically.
First, I have namespace LCD. Then I have two separate files, LCDText.h and LCDGraphic.h.
LCDText.h:
//[snip]
void TextDraw(Widget *w);
void TextBarDraw(Widget *w);
void TextHistogramDraw(Widget *w);
void TextIconDraw(Widget *w);
void TextBignumsDraw(Widget *w);
void TextGifDraw(Widget *w);
}; // End namespace
LCDGraphic.h:
//[snip]
void GraphicDraw(Widget *w);
void GraphicIconDraw(Widget *w);
void GraphicBarDraw(Widget *w);
void GraphicHistogramDraw(Widget *w);
void GraphicBignumsDraw(Widget *w);
void GraphicGifDraw(Widget *w);
}; // End namespace
And in WidgetBignums.h I have:
//[snip]
using namespace LCD;
extern void TextBignumsDraw(Widget *w);
extern void GraphicBignumsDraw(Widget *w);
template <class T>
WidgetBignums<T>::WidgetBignums(Generic<T> *v, std::string n, Json::Value *section,
int row, int col) : Widget(n, section, row, col,
WIDGET_TYPE_BIGNUMS | WIDGET_TYPE_RC | WIDGET_TYPE_SPECIAL) {
if( v->GetType() == LCD_TEXT )
Draw = TextBignumsDraw; // Line 66
else if( v->GetType() == LCD_GRAPHIC )
Draw = GraphicBignumsDraw;
else
Draw = NULL;
//[snip]
And I get the following linker error:
LCDControl.o: In function `WidgetBignums':
/home/starlon/Projects/LCDControl/WidgetBignums.h:66: undefined reference to `LCD::TextBignumsDraw(LCD::Widget*)'
Now here's one way to fix it, but I don't like it. I can move LCD::TextBignumsDraw outside of the LCD namespace and it works. Strange enough, the linker sees LCD::GraphicBignumsDraw. Any clues?
Edit: I'm using gcc 4.4.1-2 on Fedora 11. Using SCons to compile.
Edit: Here's WidgetBignums, showing Draw.
template <class T>
class WidgetBignums : public Widget {
Generic<T> *visitor_;
std::vector<char> FB_;
std::vector<char> ch_;
int min_;
int max_;
int update_;
int layer_;
Property *expression_;
Property *expr_min_;
Property *expr_max_;
QTimer *timer_;
void (*Draw)(Widget *);
public:
WidgetBignums(Generic<T> *visitor, std::string name, Json::Value *section, int row, int col);
~WidgetBignums();
void TextScroll() {};
void SetupChars();
void Update();
void Start();
void Stop();
std::vector<char> GetFB() { return FB_; }
std::vector<char> GetCh() { return ch_; }
Generic<T> *GetVisitor() { return visitor_; }
};
Edit: Here's TextBignumsDraw's signature.
//[snip]
void TextBignumsDraw(Widget *w) {
//[snip]
Edit: Incidentally, I'm getting the same error for TextHistogramDraw and TextGifDraw as well. TextIconDraw and the others are fine.
Where is the definition for LCD::TextBignumsDraw()? That's what the linker seems to be complaining about. Not the declaration, but the actual definition of the function.
The fact that when you move the declaration out of namespace LCD things start working indicates that the definition for TextBignumsDraw() is in the global namespace, not the LCD namespace.
This (in some .cpp file):
void TextBignumsDraw(Widget *w) {
// ...
}
Needs to be wrapped in a
namespace LCD {
}
block.
Try dropping the "using namespace LCD", and change that line 66 to:
Draw = LCD::TextBignumsDraw;
That's more explicit, which may help the linker understand what you're asking for.
Besides, you should never say "using namespace Anything" in a header file. It hoists everything in that namespace out into the global space for every user of that header. That almost completely destroys the value of having a namespace in the first place. You should hoist things out like this in the narrowest scope that's practical. Sometimes I put "using namespace foo" at the top of a single function, for instance, if that's the only user of the bits in the namespace within a given .cpp file.