Beginner here - but i was uncertain what exactly to search for this (presumably common) question.
I am working on a program where I have a given class (Dictionary). I am supposed to make a concrete class (Word) which implements Dictionary. I should mention that I am not to change anything in Dictionary.
After making a header file for Word, I define everything in word.cpp.
I am unsure if I am doing this correctly, but I make the constructor read from a given file, and store the information in a public member of Word.
(I understand that the vectors should be private, but I made it public to get to the root of this current issue)
dictionary.h
#ifndef __DICTIONARY_H__
#define __DICTIONARY_H__
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
using namespace std;
class Dictionary
{
public:
Dictionary(istream&);
virtual int search(string keyword, size_t prefix_length)=0;
};
#endif /* __DICTIONARY_H__ */
word.h
#ifndef __WORD_H__
#define __WORD_H__
#include "dictionary.h"
class Word : public Dictionary{
public:
vector<string> dictionary_words;
vector<string> source_file_words;
Word(istream &file);
int search(string keyword, size_t prefix_length);
void permutation_search(string keyword, string& prefix, ofstream& fout, int& prefix_length);
};
#endif /* __WORD_H__*/
word.cpp
#include "word.h"
Word(istream& file) : Dictionary(istream& file)
{
string temp;
while (file >> temp)
{
getline(file,temp);
dictionary_words.push_back(temp);
}
}
In word.cpp, on the line "Word::Word(istream& file)", I get this error :' [Error] no matching function for call to 'Dictionary::Dictionary()'.
I've been told this is error is due to "Word's constructor invoking Dictionary's ", but I still don't quite grasp the idea well. I am not trying to use Dictionary's constructor, but Word's.
If anyone has an idea for a solution, I would also appreciate any terms related to what is causing this issue that I could look up - I wasn't even sure how to title the problem.
Your child class should invoke parent constructor, because parent object are constructed before child. So you should write something like:
Word::Word(isteam& file) : Dictionary(file)
{
...
}
Seems its better described here What are the rules for calling the superclass constructor?
Related
I have some experience with Java and C, but only now starting with C++.
I am trying to write a kind of logical tree :
All items derive from an abstract base class "Item".
Some items are containers and can contain several items. They derive from class "Block". A block can contain other blocks (this is recursive).
It also has an operator information
Other elements are runnables, they don't contain other items.
So far I could build my tree (and incidentally reflect it into/from an xml file using pugixml lib).
But now in my application, I would like to easily "move myself" along the tree.
The issue is that I need to keep a pointer to the container in which an item is stored, so i can move back. (very first block will have 'nullptr')
so I have : (of course there are #ifdef guardblocks that I don't copy here)
in item.h :
#include "block.h" //issue here!
enum Item_t { ... };
class Item
{
public:
Item(Block* parentBlock, int order_number, int loop_number=1);
virtual ~Item();
virtual Item_t getItemSubClass() const = 0; //just for some kind of reflexivity hack for other function (here in this sample to show this is abstract)
protected:
Block* m_parentBlock;
int m_order_number;
int m_loop_number;
int m_current_loop=0;
private:
};
and in block.h :
#include "item.h"
#include <string.h>
#include <map>
#include <iostream>
enum Operator { undefined, serial, parallel };
//class Item; // <= forward declaration ? won't work !
typedef std::map<int, Item*>::const_iterator item_iterator_t;
class Block : public Item
{
public:
Block(Block* parentBlock, int order_number, std::string op_str, int loop_number=1);
virtual ~Block();
void addSubItem(int index, Item* item);
const Item* getSubItem(int index) const;
item_iterator_t item_begin() const;
item_iterator_t item_end() const;
Operator getOperator(void) const;
virtual Item_t getItemSubClass() const override;
protected:
private:
Operator m_op;
std::map<int, Item*> m_subItems;
};
Issue here :
Item needs to include block.h, as it has member pointer to it, AND its constructor in cpp file calls block.addSubItem() method.
Block obviously needs to include item.h as it derives from it.
forward declaration is not enough when needing to call a method or inherit from a class (so for both cases).
I could slightly change the design, by not setting parent/child relation into the constructor (this would work fine, but i'm interesting in seeing a solution to this inheritance/recursion issue)
As I was writing my question I found out a solution.
My problem was due to my coding style, where I tend to have my class.cpp files only include my corresponding class.h file, and centralize all other include command in the header. (finally it is maybe not a good practice)
in block.h : (no other choice to inherit)
#include "item.h"
in item.h : use forward declaration
class SeqBlock;
in item.cpp : include both !
#include "item.h" //optional as included in block.h but make it clear
#include "block.h"
(not sure however this is the best solution or if the original design has a big flaw)
I have multiple classes in my program.
A) When I create an object of a class in another class I am getting no error but when I use the object to call a function I get the above error.
B)Also if I create an object of another class and call a function using that in the constructor of my class then I get no error like this.
C) Cout function does not work in the body of the class except when I put it any function
D) The main class is able to do all of these and I am not getting any error.
It would be great to hear back soon. Thank you in advance.
Following is the code : These are two classes in my cpp. I am facing no problems except using object after creating it. the code is too huge too be posted. Everything can be done in main but not in other classes why?
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <cstdlib>
#include <vector>
#include <map>
using namespace std;
class Message
{
public:
void check(string side)
{
if(side!="B"&&side!="S")
{
cout<<"Side should be either Buy (B) or Sell (S)"<<endl;;
}
}
};
class Orderbook
{
public:
string side;
Orderbook() //No Error if I define inside constructor
Message m; //No Error while declaring
m.check(side); //Error when I write m. or m->
};
This is a mistake:
m.check(side);
That code has to go inside a function.
Your class definition can only contain declarations and functions.
Classes don't "run", they provide a blueprint for how to make an object.
The line Message m; means that an Orderbook will contain Message called m, if you later create an Orderbook.
Calling m.check(side), meaning you are running actual code, but you can't run code outside main() - you can only define variables.
In C++, code can only appear inside function bodies or in variable initializes.
You can declare an object of a class in another Class,that's possible but you cant initialize that object. For that you need to do something like this :-->
(inside main)
Orderbook o1;
o1.m.check(side)
but that would be unnecessary. Keeping things short :-
You can't call functions inside a Class
I'm currently trying to make a game in C++. In my code I'm trying to nest my variables so that my main doesn't have a lot of includes. My problem right now though is that the value of my variables in my class aren't changing. Stepping through the code it shows it setting the value, but it doesn't work. Anyone know what's going on? Thank you in advance.
This is what I have so far:
Location.h
#ifndef LOCATION_H
#define LOCATION_H
#include <string>
class Location
{
public:
Location(void);
Location(std::string name);
~Location(void);
std::string GetName();
void SetName(std::string value);
private:
std::string m_Name
};
#endif
Location.cpp
#include "Location.h"
Location::Location(void): m_Name("") {}
Location::Location(std::string name): m_Name(name) {}
Location::~Location(void)
{
}
std::string Location::GetName()
{return m_Name;}
void Location::SetName(std::string value){m_Name = value;}
PlayerStats.h
#ifndef PLAYERSTATS_H
#define PLAYERSTATS_H
#include "Location.h"
class PlayerStats
{
public:
PlayerStats(void);
~PlayerStats(void);
Location GetLocation();
void SetLocation(Location location);
private:
Location m_Location;
};
#endif
PlayerStats.cpp
#include "PlayerStats.h"
PlayerStats::PlayerStats(void): m_Location(Location()) {}
PlayerStats::~PlayerStats(void)
{
}
Location PlayerStats::GetLocation(){return m_Location;}
void PlayerStats::SetLocation(Location location){m_Location = location;}
main.cpp
#include <iostream>
#include "PlayerStats.h"
using namespace std;
PlayerStats playerStats = PlayerStats();
int main()
{
playerStats.GetLocation().SetName("Test");
cout<< playerStats.GetLocation().GetName()<<endl;
return 0;
}
Your immediate issue is that
Location GetLocation();
returns a copy of the location, so when you call SetName here:
playerStats.GetLocation().SetName("Test");
You're changing the name of the temporary copy, and the change is lost as soon as the semicolon is hit.
More broadly, this kind of design (nesting classes and nesting includes so that main doesn't have a lot of includes, and using a.b.c() style code to access nested members) isn't great C++ style:
Having a bunch of source files that (transitively) include a bunch of header files means that changing a single header file will trigger recompilations of a bunch of source files. Compile times can be a significant issue in larger C++ projects, so reducing compile times by controlling #include's is important. Read up on "forward declarations" for more information.
Writing code like a.b.c() is considered bad object-oriented design, because it reduces encapsulation: not only does the caller have to know about a's details, it has to know about b's also. Sometimes this is the most expedient way to write code, but it's not something to be blindly done just to reduce #include's. Read up on "Law of Demeter" for more information.
If you want to set the result of playerStats.GetLocation(), you could make GetLocation() pass-by-reference (use ampersand, &, on the return argument). Otherwise you are just setting values in a temporary copy of PlayerStats::m_Location.
Alternatively, you could use the SetLocation() function.
I have multiple classes in my program.
A) When I create an object of a class in another class I am getting no error but when I use the object to call a function I get the above error.
B)Also if I create an object of another class and call a function using that in the constructor of my class then I get no error like this.
C) Cout function does not work in the body of the class except when I put it any function
D) The main class is able to do all of these and I am not getting any error.
It would be great to hear back soon. Thank you in advance.
Following is the code : These are two classes in my cpp. I am facing no problems except using object after creating it. the code is too huge too be posted. Everything can be done in main but not in other classes why?
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <cstdlib>
#include <vector>
#include <map>
using namespace std;
class Message
{
public:
void check(string side)
{
if(side!="B"&&side!="S")
{
cout<<"Side should be either Buy (B) or Sell (S)"<<endl;;
}
}
};
class Orderbook
{
public:
string side;
Orderbook() //No Error if I define inside constructor
Message m; //No Error while declaring
m.check(side); //Error when I write m. or m->
};
This is a mistake:
m.check(side);
That code has to go inside a function.
Your class definition can only contain declarations and functions.
Classes don't "run", they provide a blueprint for how to make an object.
The line Message m; means that an Orderbook will contain Message called m, if you later create an Orderbook.
Calling m.check(side), meaning you are running actual code, but you can't run code outside main() - you can only define variables.
In C++, code can only appear inside function bodies or in variable initializes.
You can declare an object of a class in another Class,that's possible but you cant initialize that object. For that you need to do something like this :-->
(inside main)
Orderbook o1;
o1.m.check(side)
but that would be unnecessary. Keeping things short :-
You can't call functions inside a Class
I am trying to create an object of "Player" inside "PlayerManager" and I am getting the error in VS2010:
Error 1 error C2512: 'Player::Player' : no appropriate default constructor available c:\program files (x86)\microsoft visual studio 10.0\vc\include\memory 631 1 Server
Player.h:
#ifndef _PLAYER_H
#define _PLAYER_H
#include <iostream>
#include <string>
using namespace std;
class Player
{
public:
Player(const string &name);
~Player(void);
private:
string name_;
};
#endif
Here is the constructor in Player.cpp:
Player::Player(const string &name)
{
}
PlayerManager.h:
'#ifndef _PLAYERMANAGER_H
#define _PLAYERMANAGER_H
#include <string>
#include <vector>
#include <iostream>
#include "Player.h"
using namespace std;
class PlayerManager
{
public:
PlayerManager(void);
~PlayerManager(void);
private:
vector<Player> players;
};
#endif'
Here is where I create the object in PlayerManager.cpp:
PlayerManager::PlayerManager(void)
{
Player test("Hello");
players.resize(1000);
for(int i=0; i < 960; i++){
players.push_back(test);
}
}
I don't understand why it is ignoring the string "Hello", I have tried creating a string object but gives same error.
I have also tried without adding the const & in the constructor but gives same error.
Any help would be appreciated, spend hours searching for an answer. Apologies if the layout is incorrect as this is my first time asking a question.
The class std::vector requires that the class you use it with has a default constructor1. You'll need to provide one for your class.
If you really don't want to provide one, you can give an instance of your class to vector in it's constructor call, so that it will use that instance instead of trying to default-construct one:
vector v(initialsize, Player("")); // or you can pass whatever string you want the default item to have
If the vector that you are using to store Players is a member variable, you'll need to pass it the default Player to use in the initialiser list:
PlayerManager::PlayerManager() : players(initialsize, Player("")) { // assuming the vector is named players
....
}
1 As R. Martinho Fernandes and Kerrek SB have pointed out in the comments, a default constructor is only required for this particular constructor of vector (the one that takes an initial size and when you don't give it a default instance) and the member function resize when called with a single argument. If you use the constructor that takes iterators or a const Allocator&, or if you use resize with the second argument, then you don't need a DC.