Seeig that i'm new to C++ I thought i'd try and write a very simple console app that populates a 2D-array and displays its contents.
But the code I've written won't compile.
Some of the errors I get are:
error C2065: 'box' : undeclared identifier
error C2228: left of '.GenerateBox' must have class/struct/union
Here is my code:
#include <iostream>
using namespace std;
int main()
{
Box box;
box.GenerateBox();
}
class Box
{
private:
static int const maxWidth = 135;
static int const maxHeight = 60;
char arrTest[maxWidth][maxHeight];
public:
void GenerateBox()
{
for (int i=0; i<maxHeight; i++)
for (int k=0; k<maxWidth; k++)
{
arrTest[i][k] = 'x';
}
for (int i=0; i<maxHeight; i++)
{
for (int k=0; k<maxWidth; k++)
{
cout << arrTest[i][k];
}
cout << "\n";
}
}
};
Any idea whats causing these errors?
The C++ compiler reads source files in a single pass, from top to bottom. You have described the Box class at the bottom, after main(), after the part where you attempt to use the class. Accordingly, when the compiler gets to the part where you say 'Box box;', it has not yet seen the class definition, and thus has no idea what 'Box' means.
Move the main function to the bottom of your code. Specifically, you need to define Box before you reference it.
The only time when you can get away with only a forward declaration (i.e. class Box;) is when you just use Box as a pointer or reference.
You have to define Box before using it. So for your small test you can put your class definition before the main.
For bigger programs, you will put your class definitions inside .h header files that you will include at the top of your source files.
Is due to pre declaration of main(). Use main after declaration of class Box.
#nikko is right. You have to declare the Box class before using it.By either cutting pasting the declarationor telling the compiler you will declare them later
try this
extern class Box;
//use box class here
//then define it later as you wish
Related
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.
I'm making a simple game involving a Player class and have made an array to hold players when they've been instantiated. The problem is, every time I run the program, I get LNK 2019 errors-"unresolved external symbol". I am not sure why this is happening or how to get it working properly. Any help would be much appreciated.
Player *player = new Player[9];
for(int i = 0; i< world1.numPlayers;i++) // ADD PLAYERS TO ARRAY
{
Player tempplayer(3,3,5,1);
player[i] = tempplayer;
}
This is the Player Class definition:
#pragma once
class Player
{
public:
Player(int width, int height, int xPos, int health );
~Player(void);
Player();
int getWidth();
int getHeight();
int getHealth();
int getPos();
void setHealth(int newHealth);
bool isAlive();
int width;
int height;
int health;
int xPos;
};
Here is the exact warning: "Error 1 error LNK2019: unresolved external symbol "public: __thiscall Player::Player(void)" (??0Player##QAE#XZ) referenced in function _main C:\Users\Alex\Documents\Visual Studio 2012\Projects\ConsoleApplication2\ConsoleApplication2\World.obj ConsoleApplication2"
Your array loop is fine.
The problem is that you didn't define in a .cpp file one or more of the class member functions that you've declared up there in your .hpp file.
We can't tell which one, because you didn't show the whole error, but ensure that they are all defined, even if only with empty definitions.
A common culprit is the destructor; when you don't need it to do anything, it's easy to forget to define it:
Player::~Player()
{
}
It may also be your default constructor:
Player::Player()
{
}
Define them all!
Martin is right that you need to assign pointers to that array. I would have thought that such an error would have given you compile time warnings.
To the linker error - The linker warning usually prints what it is unable to find. That is usually sufficient to pin point the source of error, or at least point in the right direction. Can you paste the complete warning?
Usually the link time errors are a result of undefined member functions, as mentioned in the comment by dreamlax, OR failure to include one of the libraries.
You use of class pointers, instances and constructors seems kinda off.
This is what your code should look like:
Player *player[9];
for(int i = 0; i< world1.numPlayers;i++) // ADD PLAYERS TO ARRAY
{
player[i] = new Player(3,3,5,1);
}
EDIT: Note that this only bypasses the cause of the original link error. The linker is complaining that the default constructor, Player::Player(void), cannot be found. If I'm not mistaken, its being called when you create your array with new Player[9]. Declaring it should solve this error, allowing you to keep using the original code instead of my version.
When I compile the program I am working on I get:
expected initializer before 'class'
error in my Class.h file. I looked up the error message on the internet, but couldn't find the exact error, although similar errors seem to be caused by missing semicolons but I don't see why I need one. This is the code the error points to, I have no other functions or classes before it.
class Account
{
public:
double dAccountBalance;
double dAccountChange(double dChange);
};
In the Class.cpp file the double dAccountChange(double dChange) function is defined. I don't think this is where the error is coming from but this is the code;
double Account::dAccountChange(double dChange)
{
dAccountBalance += dChange;
return 0.0;
}
When I change the code in Class.h to look like this,
;
class Account
{
public:
double dAccountBalance;
double dAccountChange(double dChange);
};
it doesn't generate an error message, but I can't work out why I need the semicolon before it as the only code I have before it are the following pre-processor lines.
#ifndef CLASS_H_INCLUDED
#define CLASS_H_INCLUDED
Any ideas on why the error is generated?
Most likely, in the header file you include immediately before class.h, you'll have something like:
class xyzzy {
int plugh;
}
without the closing semi-colon. That will make your code sequence:
class xyzzy {
int plugh;
}
class Account
{
public:
double dAccountBalance;
double dAccountChange(double dChange);
};
which is clearly invalid. Inserting a semi-colon in class.h before the first line will fix it, but it's clearly the wrong place to put it (since it means every header file you include immediately after that one would need a starting semicolon - also, it's part of the definition in the first header and should be there).
Now that may not be the exact code sequence but it will be something very similar, and the underlying reason will be a missing piece of text in the previous header.
You should go back and put it in the earlier include file.
For example, consider:
include1.h:
class xyzzy {
int plugh;
}
include2.h:
class twisty {
int little_passages;
};
main.cpp:
#include "include1.h"
#include "include2.h"
int main (void) {
return 0;
}
Compiling this produces:
include2.h:3: error: multiple types in one declaration
but placing the semicolon at the end of include1.h (or start of include2.h though we've already established that's not a good idea) will fix it.
The problem is in one of the other headers, one that you #include ahead of class.h.
If you show us the top of your main cpp file, it might give a clue.
I'm writing a simple program using SDL, but I'm running into a strange problem. First the code:
#ifndef GLOBAL_VARIABLES_H
#define GLOBAL_VARIABLES_H
#include <string>
#include <cassert>
#include "SDL.h"
#include "SDL_image.h"
using std::string;
const int SCREEN_WIDTH = 800;
const int SCREEN_HEIGHT = 600;
const int SCREEN_BPP = 32;
const string MAIN_BACKGROUND_FILENAME = "tempBackground.jpg";
SDL_Rect CARD_CLIPS[2];
const int CARD_BACK = 0;
const int CARD_FRONT = 1;
CARD_CLIPS[CARD_BACK].h = 196;
CARD_CLIPS[CARD_BACK].w = 286/2;
CARD_CLIPS[CARD_BACK].x = 286/2;
CARD_CLIPS[CARD_BACK].y = 0;
CARD_CLIPS[CARD_FRONT].h = 196;
CARD_CLIPS[CARD_FRONT].w = 286/2;
CARD_CLIPS[CARD_FRONT].x = 0;
CARD_CLIPS[CARD_FRONT].y = 0;
#endif
The error I'm getting is this:
1>c:\users\--\global variables.h(23): error C2466: cannot allocate an array of constant size 0
1>c:\users\--\global variables.h(23): error C2143: syntax error : missing ';' before '.'
1>c:\users\--\global variables.h(23): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\--\global variables.h(23): error C2371: 'CARD_CLIPS' : redefinition; different basic types
1>c:\users\--\global variables.h(18) : see declaration of 'CARD_CLIPS'
Repeat same error for each time I try to initialize an element of the SDL_Rect.
Note that the SDL part has nothing to do with the problem. If I try to declare an int array and initialize it in the same way, I get the exact same error. If I put any of this in my main.cpp it works completely fine.
Thanks for the help. Let me know if additional information is needed.
EDIT: Note that I get no errors except for when I try and use arrays in the header file. Though I do what to understand the conventional way to do things, I also want to understand why, from a fundamental standpoint, I can't declare and initialize arrays in a header file like this.
First, variable definitions shouldn't be in header files, only extern declarations.
Second, you can initialize variables (including arrays) in the definition, or assign the content as executable statements inside a function. You can't put executable statements at file scope.
Array initialization looks like this:
int a[4] = { 1, 4, 9, 16 };
not like this:
int a[4];
a[0] = 1; // ILLEGAL outside a function!
a[1] = 4;
a[2] = 9;
a[3] = 16;
This article might provide some guidelines on what should be included in a header file.
It says C in the title but of course it's applicable to C++.
As Ben Voigt has already explained, your problem has nothing to do with header files. It is simply that you have put ordinary executable statements that are not declarations, directly at namespace scope (that is, outside any function or class). You can't.
This statement is technically fine:
const int CARD_BACK = 0;
It's technically fine because it is a declaration. There is no assignment. The = here does not denote assignment, but is part of the declaration syntax, indicating that an initializer follows.
I say "technically" because you really should reserve ALL UPPERCASE names for macros, but the compiler doesn't care.
On the other hand, this statement is not OK at namespace scope:
CARD_CLIPS[CARD_BACK].h = 196;
That's because it's not a declaration, it is not introducing a new name: it's an assignment.
Oh, my eyes hurt from all that uppercase!
Cheers,
The following for creating a Global Object is resulting in compilation errors.
#include "stdafx.h"
#include <iostream>
using namespace System;
using namespace std;
#pragma hdrstop
class Tester;
void input();
class Tester
{
static int number = 5;
public:
Tester(){};
~Tester(){};
void setNumber(int newNumber)
{
number = newNumber;
}
int getNumber()
{
return number;
}
}
Tester testerObject;
void main(void)
{
cout << "Welcome!" << endl;
while(1)
{
input();
}
}
void input()
{
int newNumber = 0;
cout << "The current number is " << testerObject.getNumber();
cout << "Change number to: ";
cin >> newNumber;
cout << endl;
testerObject.setNumber(newNumber);
cout << "The number has been changed to " << testerObject.getNumber() << endl;
}
Here are the compile errors:
1>------ Build started: Project: test, Configuration: Debug Win32 ------
1>Compiling...
1>test.cpp
1>.\test.cpp(15) : error C2864: 'Tester::number' : only static const integral data members can be initialized within a class
1>.\test.cpp(33) : error C2146: syntax error : missing ';' before identifier 'testerObject'
1>.\test.cpp(33) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>.\test.cpp(49) : error C2039: 'getNumber' : is not a member of 'System::Int32'
1> c:\windows\microsoft.net\framework\v2.0.50727\mscorlib.dll : see declaration of 'System::Int32'
1>.\test.cpp(55) : error C2039: 'setNumber' : is not a member of 'System::Int32'
1> c:\windows\microsoft.net\framework\v2.0.50727\mscorlib.dll : see declaration of 'System::Int32'
1>.\test.cpp(57) : error C2039: 'getNumber' : is not a member of 'System::Int32'
1> c:\windows\microsoft.net\framework\v2.0.50727\mscorlib.dll : see declaration of 'System::Int32'
1>Build log was saved at "file://c:\Users\Owner\Documents\Visual Studio 2008\Projects\test\test\Debug\BuildLog.htm"
1>test - 6 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
How do I create a Global Class
Object correctly like I've attempted
here.
And how do I fix that "only static
const integral data members can be
initialized within a class"
And basically how do I fix the rest
of the errors so I can get this to
compile?
I like declaring Global Class Objects at file scope (I like declaring all globals at file scope) because when I have to create separate source files and do "extern" and everything it becomes extremely complicated and never works for me. Although, I do want to figure out how to do that eventually... it seems every tutorial I look at won't compile though and unless it compiles I have no idea how to recreate it!
If I can just get this to compile...then I can successfully learn how to do this. So if someone could rewrite the above to where it literally copies & pastes into Visual C++ Express 2008 and works I will finally be able to figure out how to recreate it. I'm extremely excited on seeing the fix for this! It is just I can't get Global Objects to work right! Any other information on declaring Global Class Objects...or anything for that matter is welcome!
Just start addressing the errors one by one. A lot of the errors are just cascaded from the initial errors, so it looks like there are a lot of problems when there's only a couple. Just start from the top:
1>.\test.cpp(15) : error C2864: 'Tester::number' : only static const integral data members can be initialized within a class
You can't initialize a member in the class definition unless it's static, const, and one of the integral types. Leave the "= 5" off of the declaration of number. Then you'll need to have a definition of Tester::number outside of the class definition, like so:
int Tester::number = 5;
Problem #2:
1>.\test.cpp(33) : error C2146: syntax error : missing ';' before identifier 'testerObject'
Almost exactly what it says (missing semi-colon errors can be a bit inexact in saying where the semicolon should be) - you need a semi-colon after the definition of the Tester class.
Fix those and your compilation problems go away.
The key thing is to try and take compiler errors one at a time from the top. If you get more than about 3 of them, you can probably just ignore everything after the 3rd or so because the initial error just cause the compile to into the weeds (and if they are real errors, they'll show up again in the next compile anyway).
Error C2864: either add a const modifier to your integer, or move the initialization outside the class (as in class Tester { static int number; }; int Tester::number = 5;). The latter seems more appropriate to your case.
Error C2146: you're missing a semicolon after the declaration of class Tester { ... }. It should be class Tester { ... };
The other errors are probably caused by the previous error. They should fix themselves automatically when it is fixed.
As a side note, I don't think you really want the static modifier on your member. It seems more appropriate for an instance field. You still can't initialize it in-place though (this isn't C#), you have to move the initialization to the constructor. For example:
class Tester {
int number;
static int staticNumber; // just to show you how to use a static field
public:
Tester() : number(5) {}
~Tester() {} // I suggest you remove the destructor unless you need it
int getNumber() { return number; }
void setNumber(int value) { number = value; }
static int getStaticNumber() { return staticNumber; }
static void setStaticNumber(int value) { staticNumber = value; }
};
// initialize static members *outside* the class
int Tester::staticNumber = 5;
According to this: http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=/com.ibm.xlcpp8l.doc/language/ref/cplr038.htm
Tester testerObject;
int Tester::number = 5;
I'm not positive, but I think the rest of the errors come from that one problem.
Fix that, and see how far it gets you.
the answers already here deal with why your code doesn't compile and how to correct that. however i am intrigued by your comments about "extern". it is very easy to use when you know how. you declare in one header the extern'ed variable. and then you initialise it in one file. any other file can refer to the variable by including the header. e.g.
header.h:
// ensure the file is only included once
#ifndef _HEADER_H
#define _HEADER_H
extern int foo;
#endif
// end file header.h
header.cpp
#include "header.h"
int foo = 1;
// end file header.cpp
main.cpp
#include "header.h"
#include <stdio.h>
int main(int argc, char** argv)
{
printf("%d", foo);
return 0;
}
// end file main.cpp
Whilst using static class members for global variables helps fit the oo design scheme, its more elaborate than necessary. if you don't have to follow oo strictly, just use extern, its easier and its less code.