I've written a Cell class. When I write constructor with default parameters as inline function, there is no problem
cell.h
Class Cell{
public:
Cell(int x, int y, char sign='.'):X(x), Y(y), Sign(sign){}
};
But if I want to move that implementation in my source file like this:
cell.h
Class Cell{
public:
Cell(int x, int y, char sign='.');
};
cell.cpp
Cell::Cell(int x, int y, char sign='.'):X(x), Y(y), Sign(sign){}
Compiler says:
Reversi.cpp:1144:43: error: default argument given for parameter 3 of ‘Cell::Cell(int, int, char)’ [-fpermissive]
Cell::Cell(int x, int y, char sign='.'):X(x), Y(y), Sign(sign){}
^
In file included from Reversi.cpp:7:0:
Reversi.h:16:5: note: previous specification in ‘Cell::Cell(int, int, char)’ here
Cell(int x, int y, char sign='.');
^
You're trying to specify the default parameters in both files. Only do it within the Header File, and the compiler will stop complaining.
cell.h
Class Cell
{
public:
Cell(int x, int y, char sign);
};
cell.cpp
Cell::Cell(int x, int y, char sign='.'):X(x), Y(y), Sign(sign)
{
}
Specify the default argument only in the member function declaration within the class definition in the header. Otherwise all other modules that include the header will know nothing about the default argument.
You may not declare a default argument for the same parameter more than one time in the same declarative region and the compiler says about this.
You can't create two implementations or provide two versions of default parameters.
You should provide default parameters in the header file and provide either inline implementation in the header file or in the correspondent cpp file.
cell.h
#pragma once
class Cell {
public:
Cell(int x, int y, char sign = '.');
int X;
int Y;
char Sign;
};
cell.cpp
#include "cell.h"
Cell::Cell(int x, int y, char sign): X(x), Y(y), Sign(sign) {}
Related
I have been attempting to make some code, but I am a bit new to c++ and need some help.
I cannot instantiate class Player as a pointer, because it's an "incomplete type" (or undefined type, vs says both). Below are some (simplified, albeit not very) versions of my code:
Entity.h
#pragma once
#include <vector>
class Entity
{
public:
static void init();
class EntityObject;
class Player;
static std::vector<EntityObject*> entities;
};
Entity.cpp
#include "Entity.h"
void Entity::init()
{
entities = std::vector<EntityObject*>();
}
class Entity::EntityObject
{
private:
float velX, velY, x, y;
public:
EntityObject(float xa, float ya) { x = xa; y = ya; }
float getVelX() { return velX; }
float getVelY() { return velY; }
float getX() { return x; }
float getY() { return y; }
};
class Entity::Player : EntityObject
{
public:
Player(float xa, float ya) : EntityObject(xa, ya)
{
printf("Player created");
}
};
Can anyone tell me why
#include "Entity.h"
int main(int argc, char* argv)
{
Entity::init();
Entity::EntityObject* player = new Entity::Player(10.0f, 10.0f);
Entity::entities.push_back(player);
}
gives an incomplete/undefined type?
Thanks.
Edit:
The errors are:
Both errors direct to this line: Entity::EntityObject* player = new Entity::Player(10.0f, 10.0f);
Error (active) E0070 incomplete type is not allowed
Error C2027 use of undefined type 'Entity::Player'
You defined the Entity::Player class in the .cpp file, not in the .h file. Therefore, even though the main() includes the .h file, it does not know about Entity::Player.
Entity::Player is forward declared in Entity.h.
When the compiler compiles your main.cpp module, it does not know anything about this class except that it exists, in particular it has no idea that this class as a constructor taking two float : Player(float xa, float ya)
=> Your issue is related to forward declaring, not nested class.
Read this thread to understand your problem
What are forward declarations in C++?
Read this one to understand what you can and what you can't do with forward declaration
When can I use a forward declaration?
I have a header file in a project where I am declaring a number of structs. Some of the latter structs have members that are the types of earlier declared structs. I am aware that these member structs must be declared before they are used but I have encountered an odd behaviour.
In the file below I tried to add a new member to the second struct (LUT) of type Coordinate. As yo can see the bottom struct libraryEntry has a similar member; this has been the case for a while and has caused no problems.
#ifndef STRUCTS_H
#define STRUCTS_H
#pragma once
#include <string>
#include "Enums.h"
struct Coordinate {
int X;
int Y;
Coordinate(int x, int y) : X(x), Y(y) {}
};
struct LUT {
int offset;
std::string hexCode;
bool modifiedByTrojan;
//Coordinate xyCoordinate; <======= Causes build to fail when uncommented
};
struct libraryEntry {
int id;
DeviceType deviceType;
int offSet;
Coordinate xyCoordinate;
std::string hexCode;
DeviceConfiguration deviceConfig;
libraryEntry(int idNum, DeviceType deviceType, int offSet, Coordinate xyCoordinate, std::string hexCode) :
id(idNum),
deviceType(deviceType),
offSet(offSet),
xyCoordinate(xyCoordinate),
hexCode(hexCode)
{
}
};
#endif
Adding the Coordinate member above causes the error:
'LUT::LUT(void)':attempting to refernce a deleted function
Why is this only happening in the second struct?
In the struct that works (libraryEntry), you have defined a constructor, and in your constructor you are initialising xyCoordinate using its two-arg constructor.
In the struct that fails to compile, you haven't defined any constructors, so you get the default no-arg constructor, which initialises everything, including your Coordinate member, using their default (no-arg) constructors. Coordinate doesn't have a default constructor because you declared a different constructor and that causes the default constructor to be deleted, hence your error message.
I have two classes, and this is the header of one of them:
#ifndef WRAPPER_HPP
#define WRAPPER_HPP
#include <SDL/SDL.h>
using namespace std;
class Wrapper
{
private:
//SDL_Surface *screen;
public:
static SDL_Surface *screen;
static void set_screen(SDL_Surface *_screen);
static void set_pixel(int x, int y, Uint8 color);
static void clear_screen(int r, int g, int b);
static SDL_Surface* load_image(char path[500]);
static void draw_image(SDL_Surface *img, int x, int y, int width, int height);
static void draw_line(int x1, int y1, int x2, int y2, Uint8 color);
};
#endif
I am calling Wrapper::set_screen(screen) from another file and I get this error:
In file included from /home/david/src/aships/src/Wrapper.cpp:6:0:
/home/david/src/aships/src/Wrapper.hpp: In static member function ‘static void Wrapper::set_screen(SDL_Surface*)’:
/home/david/src/aships/src/Wrapper.hpp:11:18: error: invalid use of member ‘Wrapper::screen’ in static member function
/home/david/src/aships/src/Wrapper.cpp:10:3: error: from this location
I also get a similar error for the definition of every single function on Wrapper.cpp, for example:
void Wrapper::set_pixel(int x, int y, Uint8 color)
{
/* Draws a pixel on the screen at (x, y) with color 'color' */
Uint8 *p;
p = (Uint8 *) screen->pixels + y * screen->pitch + x * screen->format->BytesPerPixel;
*p = color;
}
On compile:
/home/david/src/aships/src/Wrapper.hpp: In static member function ‘static void Wrapper::set_pixel(int, int, Uint8)’:
/home/david/src/aships/src/Wrapper.hpp:11:18: error: invalid use of member ‘Wrapper::screen’ in static member function
/home/david/src/aships/src/Wrapper.cpp:17:17: error: from this location
I know it's related to the class being static and thus the variable Wrapper.screen is not accessible or something, but I'm not sure of how to fix it. Any ideas?
You are using a static variable
static SDL_Surface *screen;
in your code.
In C++ when you declare a static variable in the .h (or .hpp) you are creating a variable that is general (static) to the class. Thus, to use it in another file you have to redeclare it (which I'm guessing you didn't) to create a variable in that file referencing the static one. In your case put this:
SDL_Surface* Wrapper::screen;
in the .cpp file.
I'm not sure the theory is well explained, but it works like that.
Your class and member (screen) are not static, which means they don't actually exist.
You can't access a non static member in a static function.
Try to make your data members to be static.
I'm not convinced that the code abstract you show us is an accurate characterization of your problem.
Your header should not include using namespace std; — it doesn't use or declare anything from the std namespace, and specifying using namespace std; is generally regarded as 'not a good idea', doubly so when it appears in a header file.
It also isn't clear that your header needs to include SDL/SDL.h. If the Uint8 type is easily isolated (not necessarily valid), then your header file can simply use a forward declaration of the SDL_Surface class. (Your implementation code will need to include SDL/SDL.h; but you should not burden the users of your wrapper class with unnecessary #include directives when simple forward declarations would suffice.)
This code is self-contained (does not need any headers), but more or less simulates what you could use, and it compiles OK:
#ifndef WRAPPER_HPP
#define WRAPPER_HPP
typedef unsigned char Uint8;
class SDL_Surface;
class Wrapper
{
public:
static SDL_Surface *screen;
static void set_screen(SDL_Surface *_screen);
static void set_pixel(int x, int y, Uint8 color);
static void clear_screen(int r, int g, int b);
static SDL_Surface *load_image(char path[500]);
static void draw_image(SDL_Surface *img, int x, int y, int width, int height);
static void draw_line(int x1, int y1, int x2, int y2, Uint8 color);
};
#endif
//#include <SDL/SDL.h>
typedef unsigned short Uint16;
class SDL_Surface
{
public:
Uint8 *pixels;
Uint16 pitch;
struct
{
Uint8 BytesPerPixel;
} *format;
};
// End of SDL/SDL.h
void Wrapper::set_pixel(int x, int y, Uint8 color)
{
/* Draws a pixel on the screen at (x, y) with color 'color' */
Uint8 *p;
p = (Uint8 *) screen->pixels + y * screen->pitch + x * screen->format->BytesPerPixel;
*p = color;
}
It also compiles without warnings. The (Uint8 *) cast (copied from the original) is unnecessary. With the class definition given, it is superfluous; if you are needing to use a cast because the type of the pixels member of SDL_Surface actually isn't Uint8, are you sure it is a good idea? And can't you use reinterpret_cast<Uint8>(screen->pixels) instead to make it clearer?
Can you reduce your problem to code analogous to this that still shows the actual error?
First post so be gentle with me...
I am trying to implement a derived class and am having problems and no matter what i try am getting compilation errors. I am sure it is something simple i have missed but am very new to this and all my research has given me no help (or i have just missed it cause i dont know what I am doing!).
This is my header file:
#ifndef WEEKDAY_H
#define WEEKDAY_H
#include <iostream>
#include <string>
#include <ctime>
using namespace std;
class DateTime{
public:
DateTime(int y, int m, int d, int h = 0, int min = 0, int s = 0);
void display();
protected:
string get_string_component(char option, tm* dateStruct);
int get_year_days(tm* dateStruct);
struct tm DTstruct;
private:
bool validate_data( int y, int m, int d, int h, int min, int s);
};
class WeekDay : public DateTime{
public:
WeekDay(int y, int m, int d, int h = 0, int min = 0, int s = 0);
void display();
};
#endif
This is an excerpt from the .cpp file that i am trying to implement:
WeekDay::WeekDay(int y, int m, int d, int h, int min, int s)
: DateTime(int y, int m, int d, int h, int min, int s),{
}
void WeekDay::display(){
}
At present I am getting the following error:
weekday.cpp: In constructor 'WeekDay::WeekDay(int, int, int, int, int, int)':
weekday.cpp:58:13: error: expected primary-expression before 'int'
weekday.cpp:58:20: error: expected primary-expression before 'int'
weekday.cpp:58:27: error: expected primary-expression before 'int'
weekday.cpp:58:34: error: expected primary-expression before 'int'
weekday.cpp:58:41: error: expected primary-expression before 'int'
weekday.cpp:58:50: error: expected primary-expression before 'int'
weekday.cpp:60:1: error: expected identifier before '{' token
If i change things around in the .cpp file i get different errors - obviously.
Basically i really don't know how to do this and have struggled trying to find the correct way...
Anyway if someone can point me in the right direction it would be greatly appreciated...
Thanks
You're using the member initialization list incorrectly. If you want to pass the values of the arguments passed to the WeekDay constructor to the constructor of DateTime, you need to remove the types:
WeekDay::WeekDay(int y, int m, int d, int h, int min, int s)
: DateTime(y, m, d, h, min, s) {
}
Consider it like calling a function (because actually, that's what it's doing). If you have a function like void foo(int x);, you don't call it by writing foo(int 5), do you?
: DateTime(int y, int m, int d, int h, int min, int s),{
remove all the "int"s from that line.
this line:
: DateTime(int y, int m, int d, int h, int min, int s),{
should be:
: DateTime(y, m, d,h, min,s) {
The offending line is this one:
: DateTime(int y, int m, int d, int h, int min, int s),{
First you have a trailing comma before the ,, then you should remove the int you put in this line: you are not defining the superclass constructor, but calling it. Think of this as an ordinary (unbound) function: you call functions with f(x), not f(int x).
The member-initializer list takes a comma separated list of data members and initializes it with the parameter you supply. int x is not a value, it's actually a syntax error in this case. However, x would be a value.
WeekDay::WeekDay(int y, int m, int d, int h, int min, int s)
: DateTime(y, m, d, h, min, s)
I was tweaking a bit of GDAL code, and am using a typedef like this
typedef CPLErr (*MYWriter)( double dfLevel, int nPoints, double *padfX, double *padfY, void * );
which is being used in a class like this
class GDALGenerator
{
...blah...
public:
MYWriter pfnWriter;
GDALGenerator( int nWidth, int nHeight, MYWriter pfnWriter, void *pWriterCBData );
...blah...
};
but in the same file, below the GDALGenerator class when I create the function like so
CPLErr MYWriter( double dfLevel, int nPoints, double *padfX, double *padfY, void *pInfo )
{}
I get this error
Error 2 error C2365: 'MYWriter' : redefinition; previous definition
was 'typedef' f:\projects\map\somecpp\somecpp.cpp 1330 MyProjectName
I'm confused, because a standard GDAL function is being used exactly like this, and it works fine (the class is in a separate DLL in that case). I just made a copy of the function with the different name, and it doesn't work.
you cannot use the type name as a function name, only as a type of a variable.
I hope this makes it clear:
CPLErr f( double dfLevel, int nPoints, double *padfX, double *padfY, void *pInfo )
{}
MYWriter foo = f;
``