I have an error that goes like this
In file included from Level.hpp:12,
from main.cpp:4:
Corridor.hpp: In method `void Game::Corridor::update()':
Corridor.hpp:41: invalid use of undefined type `class Game::Level'
Corridor.hpp:13: forward declaration of `class Game::Level'
Corridor.hpp:42: invalid use of undefined type `class Game::Level'
Corridor.hpp:13: forward declaration of `class Game::Level'
Corridor.hpp:43: invalid use of undefined type `class Game::Level'
Corridor.hpp:13: forward declaration of `class Game::Level'
Corridor.hpp:44: invalid use of undefined type `class Game::Level'
Corridor.hpp:13: forward declaration of `class Game::Level'
Corridor and Level are …
// Corridor.hpp
#ifndef GAME_CORRIDOR_HPP
#define GAME_CORRIDOR_HPP
#include <Moot/Math.hpp>
//#include <Level.hpp>
#include <GameWindow.hpp>
namespace Game
{
class Level; // <-- LINE 13
class Corridor
{
static const unsigned int defaultLevelDepth = 800;
Moot::Math::Vector3D wp1, wp2, wp3, wp4;
Moot::Math::Vector2D sp1, sp2, sp3, sp4;
Level * p_level;
public:
Corridor(Moot::Math::Vector3D setFirstPoint, Moot::Math::Vector3D setSecondPoint)
{
wp1 = setFirstPoint;
wp2 = setSecondPoint;
wp3 = setFirstPoint;
wp3.z += defaultLevelDepth;
wp4 = setSecondPoint;
wp4.z += defaultLevelDepth;
}
void update() {
sp1 = p_level->getLevelCamera().convert3DVectorWithScreenAlgorithm(wp1); // <- LINE 41 etc.
sp2 = p_level->getLevelCamera().convert3DVectorWithScreenAlgorithm(wp2);
sp3 = p_level->getLevelCamera().convert3DVectorWithScreenAlgorithm(wp3);
sp4 = p_level->getLevelCamera().convert3DVectorWithScreenAlgorithm(wp4);
//p_level->getLevelCamera();
}
void draw()//const
{
Moot::Color tempColor;
windowInstance().graphics().drawQuad( sp1.x, sp1.y, tempColor,
sp2.x,sp2.y, tempColor,
sp3.x, sp3.y, tempColor,
sp4.x,sp4.y, tempColor, 1);
}
void setLevel(Level* setLevel) {
p_level = setLevel;
}
};
}
#endif
and
// Level.hpp
#ifndef GAME_LEVEL_HPP
#define GAME_LEVEL_HPP
#include <Moot/Forward.hpp>
#include <Moot/Window.hpp>
#include <Moot/Math.hpp>
#include <GameWindow.hpp>
#include <Camera.hpp>
#include <Corridor.hpp>
#include <Player.hpp>
#include <vector>
namespace Game
{
class Level
{
typedef Corridor* p_corridor;
typedef std::vector<p_corridor> CorridorList;
typedef CorridorList::reverse_iterator ReverseCorridorItter;
CorridorList m_map;
Camera m_camera;
Player m_player;
public:
Level()
{
m_player.setLevel(this);
// Lots of vertices being defined into m_map.
// Loop through and set camera
ReverseCorridorItter rit;
for(rit = m_map.rbegin(); rit != m_map.rend(); rit++)
(*rit)->setLevel(this);
}
~Level()
{
ReverseCorridorItter rit;
for(rit = m_map.rbegin(); rit != m_map.rend(); rit++)
delete (*rit);
m_map.clear();
}
void update()
{
// Temp delete when input and player are implimented.
if(pad[0].buttons & PAD_UP)
m_camera.updateTargetOffsets(0, -2);
if(pad[0].buttons & PAD_DOWN)
m_camera.updateTargetOffsets(0, 2);
if(pad[0].buttons & PAD_LEFT)
m_camera.updateTargetOffsets(-2, 0);
if(pad[0].buttons & PAD_RIGHT)
m_camera.updateTargetOffsets(2, 0);
m_player.update();
ReverseCorridorItter rit;
for (rit = m_map.rbegin(); rit != m_map.rend(); rit++)
(*rit)->update();
}
void draw() // const // EH!!! wtf ReverseIter isn't a member
{
m_player.draw();
ReverseCorridorItter rit;
for (rit = m_map.rbegin(); rit != m_map.rend(); rit++)
(*rit)->draw();
}
Camera& getLevelCamera() {
return m_camera;
}
};
}
#endif
The pointer is being set as far as I can tell, but when I try to access a function from Level, BOOM!
Thanks.
PS: The compiler is gcc 2.95.2 if that makes a difference.
EDIT
Updated with complete code.
0 / 0 / 0 Регистрация: 13.01.2013 Сообщений: 9 |
|
1 |
|
13.01.2013, 13:57. Показов 14005. Ответов 13
Привет! Но, проблемы с компиляцией: Я прочитал, что надо вместо #include «мой класс.h» вставить class мой класс; но это тоже не помогло: Можете помочь с инфой как правильно декларировать в таком случае? Нужно решение независимо от компилятора. —
0 |
Croessmah Неэпический 17819 / 10592 / 2044 Регистрация: 27.09.2012 Сообщений: 26,636 Записей в блоге: 1 |
||||
13.01.2013, 14:06 |
2 |
|||
Можете помочь с инфой как правильно декларировать в таком случае? Нужно решение независимо от компилятора. А код?
1 |
Setneros 0 / 0 / 0 Регистрация: 13.01.2013 Сообщений: 9 |
||||||||
13.01.2013, 14:25 [ТС] |
3 |
|||||||
Мой случай:
0 |
Неэпический 17819 / 10592 / 2044 Регистрация: 27.09.2012 Сообщений: 26,636 Записей в блоге: 1 |
|
13.01.2013, 14:29 |
4 |
class B(A * aPointer) Это что?
B b(this); А это?
0 |
Setneros 0 / 0 / 0 Регистрация: 13.01.2013 Сообщений: 9 |
||||
13.01.2013, 14:54 [ТС] |
5 |
|||
Это что? А это? Указатель породившего класса Добавлено через 23 минуты
0 |
vxg Модератор 3376 / 2148 / 352 Регистрация: 13.01.2012 Сообщений: 8,341 |
||||
13.01.2013, 15:06 |
6 |
|||
B b(this) запись не имеет смысла + вам уже сказали что при таком опережающем использовании нельзя возвращать объекты (нужно возвращать указатели).
1 |
Setneros 0 / 0 / 0 Регистрация: 13.01.2013 Сообщений: 9 |
||||
13.01.2013, 15:25 [ТС] |
7 |
|||
Как тогда в классе b вызвать функцию породившего его класса a?
0 |
Модератор 3376 / 2148 / 352 Регистрация: 13.01.2012 Сообщений: 8,341 |
|
13.01.2013, 15:35 |
8 |
никто никого не создает. просто в классах есть указатели на объекты другого класса. вызвать метод можно через p->do_something()
1 |
DU 1500 / 1146 / 165 Регистрация: 05.12.2011 Сообщений: 2,279 |
||||
13.01.2013, 15:36 |
9 |
|||
сказали же нужно просто растащить правильно по h и cpp файлам:
1 |
0 / 0 / 0 Регистрация: 13.01.2013 Сообщений: 9 |
|
13.01.2013, 15:41 [ТС] |
10 |
никто никого не создает. просто в классах есть указатели на объекты другого класса. вызвать метод можно через p->do_something() Вы видимо меня немного не допонимаете. Мне нужен способ вызвать функцию этого создавшего текущий класс класса.
0 |
Setneros 0 / 0 / 0 Регистрация: 13.01.2013 Сообщений: 9 |
||||||
13.01.2013, 16:12 [ТС] |
11 |
|||||
сказали же нужно просто растащить правильно по h и cpp файлам:
Попробовал, куча ошибок. Миниатюры
Вложения
0 |
ComfyMobile 401 / 282 / 34 Регистрация: 24.07.2012 Сообщений: 916 |
|
13.01.2013, 16:20 |
12 |
класс объект, объект класс, у ТС каша в голове, вам в любом случае нужно будет 2 объекта иначе никак Добавлено через 1 минуту
0 |
Неэпический 17819 / 10592 / 2044 Регистрация: 27.09.2012 Сообщений: 26,636 Записей в блоге: 1 |
|
13.01.2013, 16:21 |
13 |
Попробовал, куча ошибок. Вот точно такой код компилируется без проблем. Что-то, где-то Вы намудрили!
1 |
0 / 0 / 0 Регистрация: 13.01.2013 Сообщений: 9 |
|
13.01.2013, 16:25 [ТС] |
14 |
Вот точно такой код компилируется без проблем. Что-то, где-то Вы намудрили!
Да, простите, виноват.
0 |
I have the following errors trying to use a TFT library function inside my library. My library uses the pointer to an instance of the TFT library in the constructor, as well described there:
Basic C++ programming, how to pass constructor argument into class?
The errors are:
error: invalid use of incomplete type 'class TFT'
_TFTscreen->background(0, 0, 0);
error: forward declaration of 'class TFT'
class TFT;
MESmenu.h:
#ifndef _MESMENU_H_
#define _MESMENU_H_
#include <SPI.h>
#include <SD.h>
class TFT;
class MESmenu{
public:
MESmenu(TFT* pTFT) : _TFTscreen(pTFT) {};
void start();
void execute();
private:
TFT* _TFTscreen;
};
#endif
MESmenu.cpp:
#include "Arduino.h"
#include "MESmenu.h"
void MESmenu::start(){
_TFTscreen->background(0, 0, 0);
_TFTscreen->text("starting menu...", 0, 0);
//...
}
void MESmenu::execute(){
//some code...
}
The Arduino sketch is:
#include <SPI.h>
#include <SD.h>
#include <TFT.h> // Arduino LCD library
#include <MESmenu.h> // my library
// --------- TFT LCD ---------
// pin definition for the due
#define sd_cs 7
#define lcd_cs 10
#define dc 9
#define rst 8
TFT TFTscreen = TFT(lcd_cs, dc, rst);
// MES menu class
MESmenu *mainMenu = new MESmenu(&TFTscreen);
void setup() {
// initialize TFT
TFTscreen.begin();
TFTscreen.background(0, 0, 0);
// set the stroke color to white
TFTscreen.stroke(255,255,255);
TFTscreen.fill(255,255,255);
TFTscreen.setTextSize(2);
TFTscreen.text("TEST", 0, 0);
// Start menu
mainMenu->start();
}
void loop () {
mainMenu->execute();
}
The problem is related to the function:
_TFTscreen->background(0, 0, 0);
inside the MESmenu::start() in the .cpp file.
UPDATE:
As suggested by frarugi87 I’ve updated the question with the details of .h and .cpp files.
Those file are in the ArduinolibrariesMESmenu folder.
I try to change
class TFT;
with
#include <TFT.h>
and removed the #include from the main arduino sketch.
This leads to the following errors:
librariesMESmenuMESmenu.cpp.o: In function `Adafruit_GFX::image(PImage&, unsigned int, unsigned int)':
D:Softwarearduino-1.6.7librariesTFTsrc/utility/Adafruit_GFX.h:231: multiple definition of `Adafruit_GFX::image(PImage&, unsigned int, unsigned int)'
sketchtest_MESmenu_lib.ino.cpp.o:D:Softwarearduino-1.6.7librariesTFTsrc/utility/Adafruit_GFX.h:231: first defined here
librariesMESmenuMESmenu.cpp.o: In function `Adafruit_GFX::image(PImage&, unsigned int, unsigned int)':
D:Softwarearduino-1.6.7librariesTFTsrc/utility/Adafruit_GFX.h:231: multiple definition of `PImage::read16(SDLib::File)'
sketchtest_MESmenu_lib.ino.cpp.o:D:Softwarearduino-1.6.7librariesTFTsrc/utility/PImage.h:17: first defined here
librariesMESmenuMESmenu.cpp.o: In function `Adafruit_GFX::image(PImage&, unsigned int, unsigned int)':
D:Softwarearduino-1.6.7librariesTFTsrc/utility/Adafruit_GFX.h:231: multiple definition of `PImage::read32(SDLib::File)'
sketchtest_MESmenu_lib.ino.cpp.o:D:Softwarearduino-1.6.7librariesTFTsrc/utility/PImage.h:17: first defined here
librariesMESmenuMESmenu.cpp.o: In function `Adafruit_GFX::image(PImage&, unsigned int, unsigned int)':
D:Softwarearduino-1.6.7librariesTFTsrc/utility/Adafruit_GFX.h:231: multiple definition of `PImage::loadImage(char const*)'
sketchtest_MESmenu_lib.ino.cpp.o:D:Softwarearduino-1.6.7librariesTFTsrc/utility/PImage.h:17: first defined here
Forward declarations and Invalid uses of incomplete type Init
Alright, I don’t know why I should have unresolved dependency issues here, but here goes:
And to think, I was just trying to build a simple class for initializing SDL facilities.
All the tutorials I’ve been doing (lazyfoo) seem really cluttered and have all this initialization data up-front in nested if-statements in main.cpp, and I thought it looked sloppy and that I’d do one better by encapsulating all that crap into a simple class for my own uses.
Having done thirty of them, I thought I knew enough to start screwing around on my own. Maybe not?
Init.h
|
|
(Ignore the «magic consts» in the window creation function, they’re just placeholders for variables I have yet to declare.)
Init.cpp
|
|
main.cpp
|
|
build messages (backspaced over long directory names for convenience)
|
|
Look at line 14 of Init.h. There’s something missing…
A couple of things jump off the page:
— The brackets on line 6 of Init.h shouldn’t be there,
— The declaration and definition of initAll don’t match (one has no parameters, the other has two parameters)
Thanks a ton guys. Sometimes I just need a second pair of eyes that aren’t tired.
I gotta leave for work now, but I’ll take your advice when I get back!
Thanks in advance for any additional help.
Line 6 of Init.h:
|
|
Also these are non-static members of a class, so you need to have an object to act on.
|
|
But of course… having an ‘Init’ object doesn’t really make much sense. Can you have multiple Inits? Does having the object actually do anything?
These functions are all global by nature. Rather than putting them in a class, maybe put them in a namespace:
|
|
Or… if you don’t want a namespace… then make it a static class that can’t be instantiated (though that is more work for little gain).
Remember the whole point of a class is to represent a ‘thing’. They’re nouns.
Common examples of classes and what they represent:
std::string — represents a string
std::fstream — represents a file
std::list — represents a linked list of objects
etc
What exactly does an ‘Init’ represent? It’s not a ‘thing’, so it doesn’t really need to be a class.
Ah, thank you Disch. I wasn’t sure if classes NEEDED objects or not and I had forgotten about creating namespaces. I thought it was conventional to have objects of classes, but not mandatory. I had tried converting it to a struct before posting this thread, but obviously that didn’t work.
And I had thought about making an Init object (which would require me to write a constructor) but it occurred to me, like you said in your post, that it made no sense.
I’ll eventually remember all this if I fail enough times.
EDIT:
Disch! I noticed in your namespace example that you put the namespace Init member functions in main, is that truly necessary? The whole reason I decided to do this whole wrapper class thing was to keep excess stuff out of main. Should I define the functions inside the namespace, instead? Will that create problems because it’s inside a header?
Edit 2: Never mind the previous edit. Everything is in order now.
Last edited on
Topic archived. No new replies allowed.
Solution 1
In order to define a class or struct, the compiler has to know how big each member variable of the class is. A forward declaration does not do this. I’ve only ever seen it used for pointers and (less often) references.
Beyond that, what you’re trying to do here cannot be done. You cannot have a class A that contains an object of another class B that contains an object of class A. You can, however, have class A contain a pointer to class B that contains an object of class A.
B.cpp
#include "B.h"
void B::SomeFunction()
{
}
B.h
#ifndef __B_h__ // idempotence - keep header from being included multiple times
#define __B_h__
#include "A.h"
class B
{
public:
A a;
void SomeFunction();
};
#endif // __B_h__
A.h
#ifndef __A_h__ // idempotence - keep header from being included multiple times
#define __A_h__
#include "B.h"
class B; // forward declaration
struct A
{
B *b; // use a pointer here, not an object
};
#endif // __A_h__
Two points. First, be sure to use some form of idempotence to keep the headers from being included multiple times per compilation unit. Second, understand that in C++, the only difference between classes and structs is the default visibility level — classes use private visibility by default while structs use public visibility by default. The following definitions are functionally equivalent in C++.
class MyClass
{
public: // classes use private visibility by default
int i;
MyClass() : i(13) { }
};
struct MyStruct
{
int i;
MyStruct() : i(13) { }
};
Solution 2
Forward declarations, like
struct A;
or
class A;
Introduce A as an incomplete type and it remains incomplete until end of type’s definition is reached. There are things you can do with incomplete types and things you can’t. You can
- Declare variables (or members) of type «pointer to A» and «reference to A»
- Declare functions which take arguments of type A or return type A
You can’t
- Declare variables (nor members) of type A
- Dereference pointers to A or access any members of references to A
- Define subclasses of A.
In your code you try to declare struct member of incomplete type. It’s illegal. Only pointers and references are allowed.
Solution 3
public:
A a;
You are trying to create the object of A with only forward declaration. Compiler at this moment ( with only forward decl) cannot decide the size of the object A and hence, it cannot allocate memory required for A. So you cannot create objects with only forward decl.
Instead replace with:
A* a;
Pointer or reference to A without A’s class definition will work fine.
Solution 4
Two issues jump out at me here.
1: You’ve written Struct A
instead of struct A
; note the lower-case «s». Your compiler might consider the equivalent, but I don’t think it’s standard C++.
You have defined a circular reference between A
and B
. Each A object must contain a B
object, but each B
object must contain an A
object! This is a contradiction, and will never work the way you want it to. The usual C++ way to solve that problem is to use pointers or references for A::b
or B::a
(or both).
Related videos on Youtube
17 : 09
05 : 05
Forward Declaration of Class C++
15 : 10
10 : 14
Learning C++ STL — Forward List
09 : 22
C++/Game Tutorial 10: Parameters and Forward Declarations!
15 : 41
C++ Class declaration | Part-1/2 | OOPs in C++ | Lec-13 | Bhanu Priya
27 : 48
Modern C++ CLASSES — Easy and In-depth explanation | All the basics you need with examples!
39 : 47
C++ for C# and Java Developers
17 : 24
08 : 47
UE4 C++ Tutorial — #Include and Forward Declarations — UE4 / Unreal Engine 4 Intro to C++
02 : 19
C++ Forward Declaration Objects/Enums
04 : 09
Forward Declarations | Introduction to Programming with C++ | Part 43
02 : 13
Forward Declaration — Beginner C++ Tutorials
Comments
-
The follwing code is compiled in VC++6. I don’t understand why I am getting the compilation error
C2079: 'b' uses undefined class 'B'
for the following code.Class B Source
#include "B.h" void B::SomeFunction() { }
Class B Header
#include "A.h" struct A; class B { public: A a; void SomeFunction(); };
struct A Header
#include "B.h" class B; struct A { B b; };
If I changed class B header to the following, then there will be no error. But the header declaration won’t be at the top!
Class B Header with weird header declaration
struct A; class B { public: A a; void SomeFunction(); }; #include "A.h"
-
In the actual code, preprocessor macros are defined but it is not shown here to make the code simpler.
-
Double-underscores are reserved for the compiler. Use a different naming convention.
-
Double-underscores are reserved for the compiler. Use a different naming convention.
-
@GMan: I’ve always used this convention for my idempotence markings when the compiler doesn’t generate them automatically. Is this specific to a compiler or is it in the C++ spec?
-
@Matt, it is part of the C++ spec that such identifiers are reserved. I personally use «HEADER_PATH_TO_HEADER_H_INCLUDED» or «HEADER_PATH_TO_HEADER_INCLUDED» (if no «.h»).