myProgram.cpp: - class childClass
-
{
-
parentClass parent; //reference to class that created this child
-
childClass(parentClass p)
-
{
-
parent = p;
-
}
-
};
-
-
class parentClass
-
{
-
childClass child(this);
-
};
This would work fine in Java, which I'm more accustomed to, but I need to do it in C++. The problem being that C++ compilers read classes sequentially and this code gives the error "error C2061: syntax error : identifier 'parentClass'" because it does not know what parentClass is yet. All the advice on the internet says to create a forward declaration for parentClass BEFORE the definition for childClass, and then keeping the definition for parentClass after childClass, such: - class parentClass;
-
-
class childClass
-
{
-
parentClass parent; //reference to class that created this child
-
childClass(parentClass p)
-
{
-
parent = p;
-
}
-
};
-
-
class parentClass
-
{
-
childClass child(this);
-
};
But this code then gives the error: "error C2079: 'myProgram::par ent' uses undefined class 'parentClass'"
I've tried swapping around the classes, too, so that parentClass comes before childClass with a forward declaration for childClass. This gives the same error. I've also tried putting the classes in seperate *.cpp files. I must admit I don't really know how to do this, but the way I did it resulted in the same error (...uses undefined class...).
What do you think? I'm a decent Java and C# programmer but C++ is just taking the piss.
26 14868 Banfa 9,065
Recognized Expert Moderator Expert
When you forward declare a class you are just telling the compiler that a class with that name is going to exist. You can declare pointers and references from a forward declaration but you can not declare an instance of the class because the type is incomplete, the compiler only knows its name not its structure.
You can only declare an instance of the class once the class has been fully declared.
Where you declare this -
parentClass parent; //reference to class that created this child
-
you are trying to declare a instance of the parentClass, the compiler can't do this because it does not know the structure of parentClass yet. Also this is not a reference. If you want a reference or a pointer you need to declare them like this -
parentClass &parent; // reference to class that created this child
-
parentClass *parent; // pointer to class that created this child
-
My extremely limited and rusty Java is telling me that all objects are held as references in Java so you don't need to make this distinction between object, reference and pointer. Both of these declarations would work with a forward declaration.
Again the constructor you have defined for childClass takes a parentClass object as a parameter. Something that is not recomend in C++ (or C), passing whole objects of indeterminate size as parameters. Where you try to initialise it in parentClass you pass this, a pointer to the class.
I suggest you read up about C++ References and C pointers
I also note you appear to be trying to initialise child in your parentClass. The correct way to do this would be by attaching the initialisation to the definition of the constructor of the parentClass (the syntax you have used is being introduced in C++0x I believe) -
parentClass::parentClass() :
-
childClass child(this)
-
{
-
}
-
However you need to be careful when using the this pointer from the constructor as the class is not fully constructed yet so you can get odd side effects if you try to access members of the class.
Try reading Should you use the this pointer in the constructor? - parentClass parent; //reference to class that created this child
In Java I assume this would be a reference to some object. In C++ it is not. parent here is an object embedded into a child object. C++ needs to know the class layout of parent in order to determine the class layout of child.
Forward declarations simply tell the compiler a class exists: - class Mystery;
-
-
class Me {
-
Mystery * mysteryPtr; // this is fine
-
void Do(Mystery& mystery); // fine
-
Mystery mystery; // not fine
-
Mystery::InnerClass inner; // not fine
-
};
-
-
class Mystery {
-
class InnerClass {
-
//
-
}
-
};
It seems to me if you just want ChildClass to remember its parent you would make parent a parentclass* or parentclass&.
OK!! That's really helpful, I was assuming I was passing through a pointer just as in Java. As you may have guessed the code I posted was just a conceptual version, in the actual version the parent (a particle system) contains an array of children (particles) - I just want each child to have a pointer to its parent so it can ask it what it needs to look like when it respawns.
So, if I do something like this: - class childClass
-
{
-
parentClass* parent; //reference to class that created this child
-
childClass(parentClass p)
-
{
-
parent = p;
-
}
-
};
-
-
class parentClass
-
{
-
childClass child(this);
-
};
-
am I getting closer to the right idea? I will start reading those links you posted, thanks very much.
Banfa 9,065
Recognized Expert Moderator Expert
Close but you need a * in
childClass(pare ntClass *p)
Hi Banfa, I'm getting really close, I can feel it! I actually went and implemented that conceptual code in Visual Studio 2008 and I even got it to compile. So I added a variable to pass through to test it, and drew a blank. By the way, that article convinced me using "this" in the constructor was a bad idea. Here's the code, which results in the same error (..uses undefined class..) - #include "stdafx.h"
-
#include <iostream>
-
-
using namespace std;
-
-
class parentClass; //forward declaration of parentClass
-
-
class childClass
-
{
-
public:
-
parentClass * parent;
-
int someVar;
-
-
childClass(){} //default constructor
-
-
void setParent(parentClass *p)
-
{
-
parent = p;
-
}
-
-
void displayParentVar()
-
{
-
someVar = (*parent).parentVar;
-
cout << someVar;
-
}
-
-
};
-
-
class parentClass
-
{
-
public:
-
childClass child;
-
int parentVar;
-
-
parentClass()
-
{
-
parentVar = 10;
-
child = childClass();
-
child.setParent(this);
-
}
-
};
-
-
int _tmain(int argc, _TCHAR* argv[])
-
{
-
parentClass myClass();
-
return 0;
-
}
-
can you see what's wrong here?
Banfa 9,065
Recognized Expert Moderator Expert
The problem is you are still trying to use parentClass before it has been defined in childClass::dis playParentVar -
class childClass
-
{
-
public:
-
//HERE
-
void displayParentVar()
-
{
-
someVar = (*parent).parentVar;
-
cout << someVar;
-
}
-
-
};
-
All other references to parentClass in childClass just use a pointer to it but here you are trying to access a member of parentClass which is not defined yet (only forward declared) so you get an error.
Your sequence has to be - Forward Declare parentClass
- Declare childClass (only using pointers/references to parentClass)
- Declare parentClass
- Define childClass
- Define parentClass
That is why we use separate headers(h) and code (cpp) files. We put the declaration of each class into 2 separate headers and the definition of each class into 2 separate code files. The 2 code files then both include both headers (in the same order normally) so that both classes are fully declared and then each file defines the member functions their own class in full view of those declarations.
Both headers are then included into the source file containing main so that you can create an instance of parentClass.
Your code needs this structure -
// Forward declare parentClass
-
-
class childClass
-
{
-
// ... correct stuff snipped
-
public:
-
void displayParentVar();
-
};
-
-
// Declare parentClass
-
-
// definition of child class member functions
-
void childClass::displayParentVar()
-
{
-
someVar = (*parent).parentVar;
-
cout << someVar;
-
}
-
You can define class functions within the class declaration but those functions are automatically inlined so you should only do this for functions with a few lines of code (and that don't use a forward declared type).
Also note that the shorthand for
someVar = (*parent).paren tVar;
is
someVar = parent->parentVar;
Oh and that declaring someVar as a class variable is superfluous as it is only used locally to displayParentVa r so could be declared locally to that function.
I think I understand how headers work now. I can see the advantages and I'm going to split all my classes into seperate files from now on. So, I've split up the parent and the child class, made headers for them with their variables, and seperate .cpp files for their methods. The files all now #include each other.
The problem I'm getting now is error C1014: too many include files : depth = 1024. I figure its because class 1 includes class 2, which includes class 1, which includes class 2... I've tried the includes in many orders and left them out but because both classes need to know about each other I have a chicken and egg situation.
I can't see any way to resolve this because as soon as I make one class I need to have the other already made. I may have to go back to having it all in one file and use the order you suggested, but I'd really like to make it work with seperate files and headers.
JosAH 11,448
Recognized Expert MVP
Use a guard that protects the preprocessor from going all the way down: -
// parent.h:
-
#ifndef PARENT_H
-
#define PARENT_H
-
#include <child.h>
-
-
// your parent.h stuff here
-
-
#endif
-
-
// child.h:
-
#ifndef CHILD_H
-
#define CHILD_H
-
#include <parent.h>
-
-
// your child.h stuff here
-
-
#endif
-
kind regards,
Jos
Sign in to post your reply or Sign up for a free account.
Similar topics |
by: Plok Plokowitsch |
last post by:
After over a decade of programming in C++ I seem to have missed some
substantial point (mental note: am I getting too old for this?). A
little bit of help would be *very* appreciated.
I'm trying to gather various different classes into a common namespace
using typedefs:
class QWidget {};
class MyListview {};
namespace gui
|
by: Michael Sgier |
last post by:
Hello
with the original code below I get the error:
"forward declaration of `struct CPlayer'"
class CPlayer; // what does this do? Instantiate the class CPlayer?
// what's a forward declaration?
class CEnemy : public CEntity
{
public:
|
by: Eckart Haug |
last post by:
I'm working with C# objects from managed C++ using the gcroot template.
There'a a C++ header containing the definition of a C++ class:
#using <mscorlib.dll>
#include <vcclr.h>
#using <CSharpModule.dll>
class CPlusPlusClass
|
by: Eckart Haug |
last post by:
Thanx for the quick reply. Your suggestion would mean that I'd have to add a C# reference to any C++ module
that includes the C++ header. There's lots of them and I'd (for the moment) like to have the C++ <-> C#
interface encapsulated in one C++ module.
Vladimir Nesterovsky wrote:
> You can add your C# assembly in a project's references thus you may not import it explicitly.
> --
|
by: HappyHippy |
last post by:
Hi,
I have a question about forward declaration of classes.
First of all, a simple working example, which compiles and works with no
problems.
///file class_a.h:/
#ifndef __CLASS_A_H__
#define __CLASS_A_H__
| |
by: toton |
last post by:
Hi,
I have two namespace contains class InkFrame and PrefDialog
respectively. PrefDialog needs InkFrame to show the dialog over the
frame. It also stores a pointer to InkFrame inside it.
Now I want InkFrame to be forward declared in the PrefDialog header
file rather than to be included. I want to include it in the cpp file
instead. There is no harm including it in PrefDialog header, and it
works. But I want to save some compilation time....
|
by: Hunk |
last post by:
Hi
I have a question on usage of forward declarations of templates. While
searching through this group , people suggested using forward
declarations and typedefs for templates as
// in myfile.h
template<typename T,typename R>
class some_class;
|
by: Steve |
last post by:
Hi,
I always though to return an instance of a class by value, it had to be
defined - i.e. forward declaration isn't good enough?
Consider the following code snippet:
class RGBA;
class Colour
|
by: RedLars |
last post by:
Need some help with a couple of questions. Previously I have seen this
declaration;
struct Student
{
int age;
char name;
};
and this definition of an object;
struct Student stud;
|
by: marktang |
last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look !
Part I. Meaning of...
|
by: Hystou |
last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it.
First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
| |
by: Oralloy |
last post by:
Hello folks,
I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>".
The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed.
This is as boiled down as I can make it.
Here is my compilation command:
g++-12 -std=c++20 -Wnarrowing bit_field.cpp
Here is the code in...
|
by: Hystou |
last post by:
Overview:
Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
|
by: isladogs |
last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM).
In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules.
He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms.
Adolph will...
|
by: TSSRALBI |
last post by:
Hello
I'm a network technician in training and I need your help.
I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs.
The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols.
I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
|
by: adsilva |
last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
|
by: 6302768590 |
last post by:
Hai team
i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
| |
by: muto222 |
last post by:
How can i add a mobile payment intergratation into php mysql website.
| |