Forward declaration for struct and nested struct - c++

Is any way to use forward declaration for struct X and Y which is nested as I I need to use them in the hpp for some of the class members, but I would like to have them in the cpp because my hpp is included in many places
Thank you so much for any help!
//F1.hpp
#ifndef F1_HPP_
#define F1_HPP_
struct X;
struct Y
{
struct Y1
{
int y1;
};
X x1;
};
class Y1
{
public:
void f(X x);
void f2(Y::Y1 y1);
};
#endif // F1_HPP_
//F1.cpp
#include "F1.hpp"
#include <iostream>
struct X
{
int x;
int x2;
int x3;
};
void Y1::f(X x)
{
std::cout<<"-1-\n";
}
// main.cpp
#include <iostream>
#include "F1.hpp"
using namespace std;
int main()
{
X x;
Y1 f1;
f1.f(x);
return 0;
}

Short Answer: No (as far as my c++ knowledge concern)
Why:
First, if you want to declare a variable of any type you need to know the exact size of the type. That is why forward declaration is not enough BUT pointers.
Because size of pointers are always the same no matter the data type, you can use forward declaration for pointers.
Nested Types:
As far as I know of C++ we can't nest types with just variables BUT pointers.
You can use pointers and forward declaration to nest types.
Maybe something like this:
struct Y
{
struct Y1
{
int y1;
};
X* x1;
};
class Y1
{
public:
void f(X* x);
void f2(Y::Y1* y1);
};

We cannot have a nonstatic data member of incomplete type. In particular, with only a forward declaration for X, we cannot define a data member of type X as you've done inside F1.hpp. This can be seen from type:
Any of the following contexts requires type T to be complete:
declaration of a non-static class data member of type T;
Better would be to create separate header and source file for each class and then include the header wherever needed/required as shown below:
Yfile.h
#ifndef F1_HPP_
#define F1_HPP_
#include "Xfile.h" //needed for X x1; data member
struct Y
{
struct Y1
{
int y1 = 0;
};
X x1;
};
#endif
Xfile.h
#ifndef X_H
#define X_H
#include <iostream>
struct X
{
int x = 0;
int x2 = 0;
int x3 = 0;
};
#endif
Y1file.h
#ifndef Y1_H
#define Y1_H
#include "Yfile.h"
//forward declarations for parameters
struct X;
class Y1
{
public:
void f(X x);
void f2(Y::Y1 y1);
};
#endif
Y1file.cpp
#include "Y1file.h"
#include "Xfile.h"
#include "Yfile.h"
void Y1::f(X x)
{
std::cout<<"-1-\n";
}
void Y1::f2(Y::Y1 y1)
{
std::cout<<"f2"<<std::endl;
}
main.cpp
#include "Xfile.h"
#include "Y1file.h"
int main()
{
X x;
Y1 f1;
f1.f(x);
return 0;
}
Working demo
The output of the above program is:
-1-

Related

How to use typedef in header file cpp

I have created a new type using typedef and a struct. I want to export that type as a module.
I have the following cpp header file:
//header.h
#ifndef VECTOR_H
#define VECTOR_H
typedef struct {
float x;
float y;
float z;
} Vector;
#endif
#ifndef PLANE_H
#define PLANE_H
class Plane {
public:
//this works
Vector n;
//this does not work
Plane(Vector P1, Vector P2, Vector);
};
#endif
This is the module file:
//module.cpp
#include header.h
typedef struct {
float x;
float y;
float z;
} Vector;
class Plane {
public:
Vector n;
Plane(Vector P1, Vector P2, Vector P3) {...}
};
And in this file, I create an object of the class Plane calling the constructor:
//main.cpp
#include header.h
float distance = 10;
int main() {
Vector P1 = { 0, 0, 11.5 };
Vector P2 = { 0, distance, 10 };
Vector P3 = { distance, distance, 5 };
Plane E(P1, P2, P3);
return 0;
}
This throws the following error:
undefined reference to `Plane::Plane(Vector, Vector, Vector)'
What causes this error and how can I resolve it?
I use the following command to compile:
g++ main.cpp header.h
You seem to be copying the Plane class's declaration, while an include is enough, so change your module.cpp file into something like:
#include "header.h"
Plane::Plane(Vector P1, Vector P2, Vector P3)
{
}
Note that above does define what the header does declare, in C and C++, we can separate the declaration from definition
(I mean, method or function's {} body).

Using a member function pointer within a class with global typedef

I get a compiler error at the line func = &Fred::fa; saying:
[Error] '((Fred*)this)->Fred::func' cannot be used as a member pointer
since it is of type 'fptr {aka double (*)(int, int)}. However, I know that if I define the typedef as a class inside the class
typedef double (Fred::*fptr)(int x, int y);
then it will not error it. But I want to be sure that the typedef is defined outside the class.
What am I doing wrong?
#include <iostream>
typedef double (*fptr)(int x, int y);
class Fred
{
private:
//typedef double (Fred::*fptr)(int x, int y);
fptr func;
public:
Fred()
{
func = &Fred::fa;
}
void run()
{
int foo = 10, bar = 20;
std::cout << (this->*func)(foo,bar) << '\n';
}
double fa(int x, int y)
{
return (double)(x + y);
}
};
int main ()
{
Fred f;
f.run();
return 0;
}
A function and a method are different. You cannot stuff a pointer to the method in a pointer to a function. So
typedef double (*fptr)(int x, int y);
must be
typedef double (Fred::*fptr)(int x, int y);
or you must use a wrapper that hides the differences such as std::function.
What's missing in
#include <iostream>
typedef double (Fred::*fptr)(int x, int y); // Fred unknown.
class Fred
{
...
}
is a forward declaration for Fred. You can't use Fred is the compiler doesn't know Fred exists.
Solution: Forward declare Fred.
#include <iostream>
class Fred;
typedef double (Fred::*fptr)(int x, int y); // Fred known enough to get pointers
class Fred
{
...
}
But what you really want is std::function.

Issue with forward declaring class

So I am trying to forward declare a class in my C++ project and then create it in main.
So I have player_obj.cpp which contains the class, classes.h which forward declares the class, and main.cpp which uses it.
classes.h
#ifndef CLASSES_H
#define CLASSES_H
class player_class
{
public:
int x;
int y;
char sprite;
int xprevious;
int yprevious;
private:
bool active;
public:
void update_xy();
player_class(int _x, int _y, char _sprite);
void step();
void destroy();
};
#endif
main.cpp
#include <iostream>
#include "classes.h"
using namespace std;
int main()
{
player_class player_obj (5,5,'#');
cout << player_obj.x << ", " << player_obj.y << endl;
return 0;
}
and player_obj.cpp
#include <iostream>
#include <Windows.h>
using namespace std;
class player_class
{
public:
//Coordinates
int x;
int y;
//Sprite
char sprite;
//Previous coordinates
int xprevious;
int yprevious;
//Not everyone can set the activity
private:
//Active
bool active;
//Update xprevious and yprevious - Called by the step event
void update_xy()
{
xprevious = x;
yprevious = y;
}
//All functions public
public:
//Create event/Constructer
player_class(int _x, int _y, char _sprite)
{
//Set default variables
x = _x;
y = _y;
sprite = _sprite;
xprevious = x;
yprevious = y;
active = true;
}
//Step event
void step()
{
//Update old xprevious and yprevious
update_xy();
//Do other stuff here
}
//Drestroy event
void destroy()
{
active = false;
}
};
I thought that would work out all right but when I compile and run it I get:
main.cpp:(.text+0x2c): undefined reference to`player_class::player_class(int, int, char)'
I've done some research, but I can't seem to fix this issue.
I greatly appreciate any help!
Well you're sort of close, what you have in your header is indeed a class declaration (not a forward declaration mind you).
The problem is you never defined it. What you have in player_obj.cpp is an abomination of class redefinition, but you already have your class declared. Just include the header file and define the functions one by one and you're done!
#include "classes.h"
player_class::player_class(int _x, int _y, char _sprite)
{
//Set default variables
x = _x;
y = _y;
sprite = _sprite;
xprevious = x;
yprevious = y;
active = true;
}
// and so on
If you're serious about learning modern C++ though, a few notes:
#pragma once is the modern way of guarding header files. Don't use those #ifdef..#endif constructs.
generally speaking, don't name anything starting with underscores. Especially not parameters visible as part of your public contract.
you have class initializers for a reason, use them! You don't need half a screen of copy pasting variables in your constructors.
You dont want a forward declaration. You want a declaration. It is a classical case of declaring a class in a header file and defining its functions in a cpp file. Then including the header where-ever you want to use your class
You only need forward declarations when you want to use a pointer to that class as a parameter to a function or a member variable somewhere but the definition of that class is not available yet.
Note that when you forward declare a class, you cannot use this class's member variables or functions in that header
-regards
Gautam

Way around "first defined here" error?

I need to have two alternate classes with the same name, that I can switch between each other by simply changing which class is included in main.
For example;
Mode_1.h
class Draw{
private:
// private stuff
public:
void Render(int x, char y);
};
Mode_2.h
class Draw{
private:
// private stuff
public:
void Render(int x, char y);
};
main.cpp
#include "Mode_1.h"
int main(){
Draw D;
int x = 2;
char y = 'x';
D.Render(x, y);
}
Currently I'm having to comment out the .h and .cpp files I'm not using to avoid the "first defined here" error. What I want is that all I have to do to switch between them is change
#include "Mode_1.h"
to
#include "Mode_2.h"
You should put them in different namespaces:
namespace Mode2
{
class Draw{
private:
// private stuff
public:
Draw(int x, char y);
};
}
In main you can then select the namespace you want to use:
#include "Mode_1.h"
#include "Mode_2.h"
using namespace Mode2;
int main()
{
Draw D;
int x = 2;
char y = 'x';
D.Draw(x, y);
return 0;
}
You may try like this:
#ifdef MODE1
#include "Mode_1.h"
#else
#include "Mode_2.h"
#endif
int main(){
Draw D;
int x = 2;
char y = 'x';
Draw(x, y);
}
And compile this source file with -DMODE1 or none depending on you wish to include Mode_1.h or Mode_2.h

C++ inherited functions not being found

I new in C++ and I have difficulty to understand how to get my function with inheritance.
I have a Class that is link to another with inheritance, everything work except:
I cannot reach my superclass function.
Here's my class header : Point.h (I don't include the .cpp):
#ifndef Point_H
#define Point_H
#include <iostream>
class Point{
public:
Point();
void set_values (int , int);
void set_values (int , int , int );
void affichervaleurs();
int getX() const { return x; }
int getY() const { return y; }
private:
int x ;
int y ;
int z ;
};
#endif
Now My other class that try to access the function getX from Point.h :
The header : Carre.h
#ifndef Carre_H
#define Carre_H
#include "Point.h"
class Carre : public Point{
public:
Carre();
//Carre(int a , int b);
//Carre(int a, int b):Point(a,b) {};
//Carre(int a, int b, int c):Point(a, b, c) {};
//const Point &pp;
int Aire (){
};
void affichercar(){
};
};
#endif
Carre.cpp
#include <iostream>
using namespace std;
#include "Carre.h"
#include "Point.h"
Carre::Carre():Point(){
};
//Carre::Carre(int a, int b);
//const &pp;
int Aire (){
return (getX() * getY());
};
void affichercar(){
//cout << "Coordonnees X:" << x << endl;
};
It says that my GetX() is undeclared in my Carre.cpp .
Like I said I'm new in C++
Does someone know what I'm missing to make that code work. ?
Your definition is missing the class scope, which makes it a free function instead of a member.
It should be
int Carre::Aire (){
return getX() * getY();
};
In the .cpp file for Carre, the functions Aire and affichercar are global. Presumably you intended:
int Carre::Aire(){
return (getX() * getY());
};
For example.
Declaring function outside class body requires a class specifier:
int Carre::Aire () {
return (getX() * getY());
};
void Carre::affichercar() {
//...
}
Otherwise
int Aire () {
return (getX() * getY());
};
is just another function in global namespace that can exists simutaneously to Carre::Aire().
This is because you are not implementing the Aire function as being part of the Carre class.
Try changing
int Aire (){
to
int Carre::Aire (){
Also, you already have an implementation of the Aire method in the header file. You should either implement the function inline in the header file, or in the .cpp file, but not both. This also applies to your affichercar method.