I am currently developing a c++ program with the main purpose being you have two different objects which float around the screen, crash into each other, etc.
Anyway the problem that I am having is that I need to derive two classes from my base class. However in the definition and declaration of my derived class I am getting an error and cant work it out. I have searched the net and sought advice from my colleagues however am unable to find the source of the problem. the code is
Jetsam(RandomNumber &rnd, Console &console);
(For the header file)
and
Jetsam::Jetsam(RandomNumber &rnd, Console &console): Element(rnd, console){};
(For the cpp file)
The error I am getting is IntelliSense:
Jetsam::Jetsam(RandomNumber &rnd, Console &console)" provides no initializer for: e:\c++\my game\my game\jetsam.cpp.
Does anyone have any idea of what is wrong. Any help would be much appreciated :)
Cheers guys, Alyn.
As requested:
JETSAM
#pragma once
#include "RandomNumber.h"
#include "Console.h"
#include "element.h"
#include <iostream>
using namespace std;
class Jetsam : public Element
{
public:
Jetsam(RandomNumber &rnd, Console &console);
~Jetsam();
void printAt(void);
protected:
RandomNumber &rnd;
Console &console;
};
Element
#pragma once
#include "RandomNumber.h"
#include "Console.h"
#include <iostream>
using namespace std;
// code shell, amend as appropriate
class Element
{
protected:
RandomNumber &rnd;
Console &console;
int x;
int y;
int energy;
int direction;
int speed;
char identifier;
static char nextIdentifier;
public:
Element();
Element(RandomNumber &rnd, Console &console);
// precondition: references to RandomNumber and Console objects are provided, along with any other desired parameters
// postcondition: Element object created and private members initialised
// example of use: Element element(rnd, console);
virtual void print(void);
// precondition: none
// postcondition: identifier, x and y are sent to the standard output
// example of use: element.print();
virtual void printAt(void)=0;
// precondition: none
// postcondition: text background is changed proportionate to its energy in the following order
// BLUE, GREEN, AQUA, YELLOW, RED, PURPLE, e.g. an object with 23 energy would have an AQUA background
// object's identifier is sent to the standard output at its x, y coordinates
// example of use: element.printAt();
int getX(void);
int getY(void);
int getEnergy(void);
int getDirection(void);
int getSpeed(void);
//getters for the base class
void setX(int);
void sety(int);
void setEnergy(int);
void setDirection(int);
void setSpeed(int);
//setters for the base class
};
The problem is that both the classes Element and Jetsam define these members:
RandomNumber &rnd;
Console &console;
This means each instance of Jetsam actually has two of these: Element::rnd and Jetsam::rnd. As they're references, they have to be initialised in the mem-initialiser list of the constructor; there's no other way to initialise them.
To simply fix the error, you'd have to do this:
Jetsam::Jetsam(RandomNumber &rnd, Console &console) :
Element(rnd, console)
, rnd(rnd)
, console(console)
{}
However, I suspect you don't really want them duplicated (especially since they're protected inside Element). So the correct solution would be to simply remove their declarations from Jetsam. After that, Jetsam would look like this:
class Jetsam : public Element
{
public:
Jetsam(RandomNumber &rnd, Console &console);
~Jetsam();
virtual void printAt(void);
};
Note that it's generally a good idea to repeat the virtual keyword when overriding virtual functions in derived classes (it helps readability), even though it's not required by the standard. Of course, with C++11 compilers which support it, override is even more preferable.
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)
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?
I can't get method overriding to work. Right now I have a class called Sprite, and two subclasses; Let's call them Goomba and Koopa. Instances of Koopas and Goombas are stored in an std::list of sprites called spriteList, and an iterator goes through this list and calls each sprite's behave() function.
I can get this to work with Goombas alone, by defining the behavior function as Sprite::behave(). But if I try to do the same thing with Koopas, the compiler gets mad because Sprite::behave() is already defined in Goomba. What am I doing wrong? I get the feeling that the answer is an extremely simple syntax issue, but looking online yielded no examples that looked quite like my code.
I'll paste some code, hopefully it'll help. This isn't my exact source code, so I apologize for any typos.
//Sprite.h:
#ifndef SPRITE_H
#define SPRITE_H
class Sprite {
private:
float xPosition; float yPosition;
public:
Sprite(float xp, float yp);
void move(float x, float y); //this one is defined in Sprite.cpp
void behave(); //this one is NOT defined in Sprite.cpp
};
#endif
//Goomba.h:
#ifndef GOOMBA_H
#define GOOMBA_H
#include "Sprite.h"
class Goomba : public Sprite {
public:
Goomba(float xp, float yp);
void behave();
};
#endif
//Goomba.cpp:
#include "Goomba.h"
Goomba::Goomba(float xp, float yp): Enemy(xp, yp) {}
void Sprite::behave(){
Sprite::move(1, 0);
}
//Koopa.h looks just like Goomba.h
//Koopa.cpp
#include "Koopa.h"
Koopa::Koopa(float xp, float yp): Enemy(xp, yp) {}
void Sprite::behave(){
Sprite::move(-2, 1);
}
In Sprite you have to declare the function as virtual
virtual void behave();
Then in Goomba you should state that you are going to override that function
virtual void behave() override;
Note: The override keyword is new as of C++11
In both Koopa.cpp and Goomba.cpp you are defining Sprite::behave. This results in two definitions, as your toolchain told you. You want to define Koopa::behave and Goomba::behave, respectively, in those files.
You also want to define Sprite::behave in Sprite.cpp (you said you currently do not define it anywhere).
You will also want to make Sprite::behave a virtual function in order to get the polymorphic behavior you are after working the way you likely expect it to:
class Sprite {
// ...
// You can either define Sprite::behave in Sprite.cpp or change the declaration to:
// virtual void behave() = 0;
// to make it "pure virtual," indicating that subclasses must provide an implementation.
virtual void behave();
};
In Goomba.cpp, for example:
#include "Goomba.h"
Goomba::Goomba(float xp, float yp): Enemy(xp, yp) {}
void Goomba::behave(){
...
}
Had some issues in my code recently surrounding what I now know of as a Circular dependency. In short there are two classes, Player and Ball, which both need to use information from the other. Both at some point in the code will be passed a reference of the other (from another class that will include both .h files).
After reading up on it, I removed the #include.h files from each one and went with forward declaration. This solved the issue of being able to declare the classes in eachother, but I'm now left with an "Incomplete type error" when trying to access a passed reference to the object. There seem to be a few similar examples around, though often mixed with more complex code and hard to narrow down to the basics.
I've rewritten the code in it's simplest form (a skeleton essentially).
Ball.h:
class Player;
class Ball {
public:
Player& PlayerB;
float ballPosX = 800;
private:
};
Player.h:
class Ball;
class Player {
public:
void doSomething(Ball& ball);
private:
};
Player.cpp:
#include "Player.h"
void Player::doSomething(Ball& ball) {
ball.ballPosX += 10; // incomplete type error occurs here.
}
Any help understanding why this is the case would be greatly appreciated :)
If you will place your definitions in this order then the code will be compiled
class Ball;
class Player {
public:
void doSomething(Ball& ball);
private:
};
class Ball {
public:
Player& PlayerB;
float ballPosX = 800;
private:
};
void Player::doSomething(Ball& ball) {
ball.ballPosX += 10; // incomplete type error occurs here.
}
int main()
{
}
The definition of function doSomething requires the complete definition of class Ball because it access its data member.
In your code example module Player.cpp has no access to the definition of class Ball so the compiler issues an error.
Player.cpp require the definition of Ball class. So simply add #include "Ball.h"
Player.cpp:
#include "Player.h"
#include "Ball.h"
void Player::doSomething(Ball& ball) {
ball.ballPosX += 10; // incomplete type error occurs here.
}
Here is what I had and what caused my "incomplete type error":
#include "X.h" // another already declared class
class Big {...} // full declaration of class A
class Small : Big {
Small() {}
Small(X); // line 6
}
//.... all other stuff
What I did in the file "Big.cpp", where I declared the A2's constructor with X as a parameter is..
Big.cpp
Small::Big(X my_x) { // line 9 <--- LOOK at this !
}
I wrote "Small::Big" instead of "Small::Small", what a dumb mistake..
I received the error "incomplete type is now allowed" for the class X all the time (in lines 6 and 9), which made a total confusion..
Anyways, that is where a mistake can happen, and the main reason is that I was tired when I wrote it and I needed 2 hours of exploring and rewriting the code to reveal it.
In my case it was because a typo.
I had something like
struct SomethingStrcut { /* stuff */ };
typedef struct SomethingStruct smth;
Notice how the name of the structure is not the same one as the type definition.
I misspelled struct to strcut.
Look into your code and see wether you have some typos.
Can anyone tell me why i get a "Block.h:20: error: multiple types in one declaration" error message when compiling this file. Nothing seems to be solving this problem and I'm getting pretty frustrated.
Displayable.h
#include <X11/Xlib.h>
#include <X11/Xutil.h>
// Information to draw on the window.
struct XInfo
{
Display *display;
Window window;
GC gc;
};
// An abstract class representing displayable things.
class Displayable
{
public:
virtual void paint(XInfo &xinfo) = 0;
};
Sprite.h
#include "Displayable.h"
enum Collision {
NO_COLLISION = 0,
TOP_COLLISION,
RIGHT_COLLISION,
BOTTOM_COLLISION,
LEFT_COLLISION
};
class Sprite : public Displayable {
public:
int x, y, width, height;
Sprite();
virtual void paint(XInfo &xinfo) = 0;
Collision didCollide(Sprite *s);
};
Block.h
#include "Sprite.h"
class Block : public Sprite {
public:
virtual void paint(XInfo &xinfo);
Block(int x, int y, int width, int height);
}; <-- **This is line 20**
As is, the code looks OK. I can't see anything wrong with the particular line. However, Xlib is a C library which likes to define quite a number of macros and conventionally uses CamelCase for macros, too. That is, I would suspect that something in your declarations actually happens to be a macro which gets expanded to something the C++ compiler doesn't like. To find this problem I recommend you use the omnipresent -E flag to have a look at the preprocessed source. That is, you'd remove any -o flag (and the name following it) and -c flag but otherwise you'd essentially retain the command line. The result will be written to standard output i.e. you want to redirect the output to more/less or some file.
Alternatively, you can go about and prefix all of your names by a prefix which is unlikely to be used in any of the X11 headers, e.g. parts of some name, offensive words, etc. I tried to reproduce the problem on my system but I didn't get an error message.