Two of my classes had to include each other. I made forward declarations instead, compilation is ok. One function of these classes is to call the destructor of the other. And that the compiler spits warnings at me, the destructor will not be called. What can I do? I can avoid this problem by creating another class for the function I need, avoiding the forward declarations but that would not be educative for me...
Here is my first class Header.h :
#ifndef H_HEADER
#define H_HEADER
#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
#include "SDL/SDL_ttf.h"
#include <string>
#include <iostream>
#include <fstream>
#include <vector>
#include <sstream>
#include "DataFiles.h"
class Character; // forward declaration Header <-> Character
class Header {
private:
Character * ch;
};
void cleanUp(std::vector <SDL_Surface*> & Vsurface, std::vector <TTF_Font*> & Vfont, std::vector <Character*> & Vchar);
// ... Other functions use in main.cpp
#endif
HEre is the Header.cpp:
#include "Header.h"
using namespace std;
void cleanUp(vector <SDL_Surface*> & Vsurface, vector <TTF_Font*> & Vfont, vector <Character*> & Vchar) {
for(unsigned int i(0); i < Vsurface.size(); i++)
SDL_FreeSurface(Vsurface[i]);
for(unsigned int i(0); i < Vfont.size(); i++)
TTF_CloseFont(Vfont[i]);
for(unsigned int i(0); i < Vchar.size(); i++)
delete Vchar[i];
TTF_Quit();
SDL_Quit();
}
And here is the other Character.h class:
#ifndef H_CHARACTER
#define H_CHARACTER
#include <string>
#include <iostream>
#include <sstream>
#include <vector>
#include </usr/include/SDL/SDL_image.h>
#include </usr/include/SDL/SDL.h>
#include </usr/include/SDL/SDL_ttf.h>
#include "DataFiles.h"
#include "CharFrame.h"
class Header; // Forward declaration Header <-> Character
class Character {
public:
Character(std::string& dataPath);
~Character();
// .. other functions
private:
Header * h;
// ... other attributes
};
#endif
And here is my Character destructor:
Character::~Character() {
cout << "Character " << m_name << " deleted.\n-----------------------------------\n" << endl;
}
So when my program ends, I call upon the Header's function "cleanUp()" giving it a vector of pointers to Characters. Every pointer should then be deleted through the Character's destructor ~Character();
However compilation gives me three warnings:
Header.cpp: In function ‘void cleanUp(std::vector<SDL_Surface*>&, std::vector<_TTF_Font*>&, std::vector<Character*>&)’:
Header.cpp:66:17: warning: possible problem detected in invocation of delete operator: [enabled by default]
Header.cpp:66:17: warning: invalid use of incomplete type ‘struct Character’ [enabled by default]
Header.h:27:7: warning: forward declaration of ‘struct Character’ [enabled by default]
Header.cpp:66:17: note: neither the destructor nor the class-specific operator delete will be called, even if they are declared when the class is defined
And once my program terminates, the character's destructor's message won't show up which means the destructor clearly isn't called.
What am I doing wrong with the forward declarations?
Yep, that's what the (draft) standard says (§5.3.5.5);
If the object being deleted has incomplete class type at the point of deletion and the complete class has a
non-trivial destructor or a deallocation function, the behavior is undefined.
(a non trivial destructor being one you defined yourself)
To fix it, just #include "Character.h" in header.cpp before invoking delete to allow the type to be completely declared.
When you use class MyClass; to forward declare your class, this only declares that the thing with the name MyClass is a class, it does not declare the internal methods of the class.
Whenever you need to use one of the internal methods (such as a non-trivial destructor) you need to include the full declaration of the class (this means include the header file containing the class definition). Without this, the compiler has no way of knowing what the internal structure of your class actually looks like.
Here is an example:
// main.cpp
#include "head1.hpp" // An instance of Head1 is created in this file
#include "head2.hpp" // An instance of Head2 is created in this file
int main(int argc, char** argv)
{
Head1 head1(true);
Head2 head2(true);
return 0;
}
// head1.hpp
#ifndef HEAD1_HPP
#define HEAD1_HPP
class Head2; // A pointer to a class is declared, but no instance is created
// so here we only need a forward declaration
class Head1
{
public:
Head1(bool real=false);
~Head1();
private:
Head2* myHead2;
};
#endif /* #ifndef HEAD1_HPP */
// head2.hpp
#ifndef HEAD2_HPP
#define HEAD2_HPP
class Head1; // Same as above
class Head2
{
public:
Head2(bool real=false);
~Head2();
private:
Head1* myHead1;
};
#endif /* #ifndef HEAD2_HPP */
// head1.cpp
#include "head1.hpp" // Include the header we are defining methods for
#include "head2.hpp" // We also create an instance of Head2 in here
#include <iostream>
using namespace std;
Head1::Head1(bool real) {
myHead2 = real ? new Head2() : NULL;
cout << "Hello Head 1" << endl;
}
Head1::~Head1() {
cout << "Bye Head 1" << endl;
if (myHead2 != NULL) delete myHead2;
}
// head2.cpp
#include "head2.hpp" // As above
#include "head1.hpp"
#include <iostream>
using namespace std;
Head2::Head2(bool real) {
myHead1 = real ? new Head1() : NULL;
cout << "Hello Head 2" << endl;
}
Head2::~Head2() {
cout << "Bye Head 2" << endl;
if (myHead1 != NULL) delete myHead1;
}
Related
I wrote down an example code to try to replicate the error I am getting in a school project about the scope of an object:
In file: classTest.cpp
#include "headerone.h"
#include "headertwo.h"
#include <iostream>
using namespace std;
int main() {
ClassOne* pntrObj1 = new ClassOne;
ClassTwo* pntrObj2 = new ClassTwo;
pntrObj1->testClassOne();
return 0;
}
In file: headerone.h
#ifndef HEADERONE_H
#define HEADERONE_H
#include "headertwo.h"
#include <iostream>
using namespace std;
class ClassOne {
public:
void testClassOne() {
cout << "One Worked\n";
pntrObj2->testClassTwo();
}
};
#endif
In file: headertwo.h
#ifndef HEADERTWO_H
#define HEADERTWO_H
#include <iostream>
using namespace std;
class ClassTwo {
public:
void testClassTwo() {
cout << "Two Worked";
}
};
#endif
To be clear, the error is: pntrObj2 was not declared in this scope. The error comes from the file headerone.h
If I had to guess, I need to somehow pass the reference but I am not sure where to start for that. Any help is appreciated.
The variable pntrObj2 is only visible inside the scope in which it was declared, in this case your function main(). In other words, only code inside the curly braces of main() would be able to use the name pntrObj2 to reference that variable. However you can pass that value to other pieces of code by making it the argument of a function call.
So maybe what you want to do is add an argument to the testClassOne() method, so you can pass in the value of pntrObj2. So pntrObj1->testClassOne(); would become pntrObj1->testClassOne(pntrObj2);, and where you define testClassOne you can add a corresponding parameter. I'll let you figure this out so as to not completely do your homework for you :)
Here you include your file a lot of time and in testClassOne function, you do not declare pntrObj2
use
void testClassOne() {
cout << "One Worked\n";
ClassTwo* pntrObj2 = new ClassTwo()
pntrObj2->testClassTwo();
}
insteed of
void testClassOne() {
cout << "One Worked\n";
pntrObj2->testClassTwo();
}
How to combine array.h, array.cpp and main.cpp files together? I am getting an error while compiling main.cpp, that class Array is not declared in scope.
main.cpp:
#include<iostream>
#include "Array.h"
#include "Array.cpp"
using namespace std;
int main(){
Array a;
a.Array();
return EXIT_SUCCESS;
}
Array.h:
#ifndef ARRAY_H_INCLUDED
#define ARRAY_H_INCLUDED
class Array{
private:
int data;// The value or data stored in the node
int ArraySize;//Size of array
int* array;
public:
Array();
};
#endif
Array.cpp:
#include <iostream>
#include <cstdlib>
using namespace std;
#include "Array.h" // user defined header file
Array::Array(){ //initialise array
cout << "Initialising array elements----------------->"<< endl;
for (int i=0; i < 4; i++){
//array[i]= 1;
cout << i << endl;
}
}
ERROR message: invalid use of 'class Array'
The problem you have is that you are attempting to call the constructor of a class on an instance of that class:
Array a;
a.Array();
When you declare a function the same name as a class, you are creating a constructor for that class.
class Array
{
public:
// Default constructor
Array();
// This is a function you can call
void PrintData();
}
You can't call this function though. It's called automatically when you create an object of class Array:
Array a; // This will call Array's constructor
a.PrintData(); // This will call the function PrintData on the object 'a'
I'm trying to create a vector which will store objects. I have added to the header file of the class as a private data member.
I am trying to initialize this vector as being empty (so that I can add objects to it later on in the program) but when I compile this program to test, this error is returned:
...error: '_bookingVector' was not declared in this scope|
I think the problem is with my initialization list on my default constructor(_bookingVector is obviously the vector):
Schedule::Schedule() : _bookingVector()
{ }
Is my syntax wrong? Or are vectors initialized differently?
Here is my code:
Schedule.h
#ifndef SCHEDULE_H
#define SCHEDULE_H
#include "Booking.h"
#include <vector>
using namespace std;
class Schedule
{
public:
Schedule();
void AddBooking(int bday, int btime, int btrainer, int bid);
void RemoveBooking(int bday, int btime);
void DisplaySchedule();
void DisplayAvailableTimeSlots();
//For Testing
void DisplayDebug();
private:
vector<Booking> _bookingVector;
};
#endif // SCHEDULE_H
Schedule.cpp
#include "Schedule.h"
#include "Booking.h"
#include <vector>
#include <iostream>
Schedule::Schedule() : _bookingVector()
{ }
void AddBooking(int bday, int btime, int btrainer, int bid){
Booking bookingObject(bday, btime, btrainer, bid);
_bookingVector.push_back(bookingObject);
}
void DisplayDebug(){
for(int i = 0; i < _bookingVector.size(); ++i){
cout << _bookingVecotr[i] << endl;
}
}
I'm very eager to learn what I'm doing wrong and fix it.
The issue is not with the constructor, which looks fine if unnecessary1. The issue is that you have defined AddBooking and DisplayDebug as non-member functions, but these should be members in order to access other members of the class.
Modify the definitions to be in the scope of the Schedule class thus:
void Schedule::AddBooking(int bday, int btime, int btrainer, int bid) { ...
^^^^^^^^^^
void Schedule::DisplayDebug(){ ...
^^^^^^^^^^
Also, don't say using namespace std in a header file (I'd go further and say don't say it anywhere but there isn't universal agreement on that.)
1 Your default constructor does not do anything that the compiler-generated one wouldn't do. You can safely remove it.
Why does my following code produce the following while compiling: error: 'Individual' in class 'Evolve' does not name a type.
#ifndef EVOLVE_H
#define EVOLVE_H
#include <cstdlib>
#include <iostream>
#include <string>
#include "Operator.h"
#include "Individual.h"
using namespace std;
class Evolve
{
public:
Evolve(int length, Operator** operators, int numOperators);
Individual* bestIndividual;
Individual* run(int generations);
Operator operatorArray[];
private:
int length;
int numOperators;
};
#endif
And my class file is
#include <cstdlib>
#include <iostream>
#include <string>
#include "Evolve.h"
#include "Operator.h"
#include "Individual.h"
using namespace std;
Evolve::Evolve(int length, Operator** operators, int numOperators)
{
Individual* bestIndividual = new Individual(length);
}
Evolve::Individual* run(int generations)
{
for(int i=0; i<generations; i++)
{
cout << "test counter = " << i << endl;
}
}
I've read a few other posts about the error and it has all been about what order to declare the function, but I'm not sure if thats the cause of my problem.
The way you implement member function is incorrect.
Update:
Evolve::Individual* run(int generations)
to:
Individual* Evolve::run(int generations)
Also, to initialize member you do not re-define it again.
Evolve::Evolve(int length, Operator** operators, int numOperators)
: bestIndividual(new Individual(length)
{
}
In your constructor,
Individual* bestIndividual = new Individual(length);
you defined a local pointer bestIndividual and it leaks memory.
The general syntax is:
return-type class-name :: function-name(arg list)
Individual* Evolve :: run (int generations)
Fix your Evolve definition
I have a problem with my C++ code. If I insert #include "god.hpp" in neuron.hpp, g++ shows me the following error:
In file included from neuron.hpp:4,
from main.cpp:5:
god.hpp:11: error: ‘Neuron’ has not been declared
god.hpp:13: error: ‘Neuron’ was not declared in this scope
god.hpp:13: error: template argument 1 is invalid
god.hpp:13: error: template argument 2 is invalid
main.cpp: In function ‘int main()’:
main.cpp:36: error: no matching function for call to ‘God::regNeuron(Neuron*&)’
god.hpp:11: note: candidates are: long int God::regNeuron(int*)
In file included from god.hpp:5,
from god.cpp:3:
neuron.hpp:10: error: ‘God’ has not been declared
In file included from neuron.hpp:4,
from neuron.cpp:2:
god.hpp:11: error: ‘Neuron’ has not been declared
god.hpp:13: error: ‘Neuron’ was not declared in this scope
god.hpp:13: error: template argument 1 is invalid
god.hpp:13: error: template argument 2 is invalid
and here are the related (parts) of the necessary files:
//main.cpp
#include <string>
#include <vector>
#include "functions.hpp"
#include "neuron.hpp"
#include "god.hpp"
using namespace std;
int main()
{
God * god = new God();
vector<string>::iterator it;
for(it = patterns.begin(); it != patterns.end(); ++it) {
Neuron * n = new Neuron();
god->regNeuron(n);
delete n;
cout << *it << "\n";
}
}
The God ;) Who will handle all neurons...
//god.hpp
#ifndef GOD_HPP
#define GOD_HPP 1
#include <vector>
#include "neuron.hpp"
class God
{
public:
God();
long regNeuron(Neuron * n);
private:
std::vector<Neuron*> neurons;
};
#endif
//god.cpp
#include <iostream>
#include <vector>
#include "god.hpp"
#include "neuron.hpp"
using namespace std;
God::God()
{
vector<Neuron*> neurons;
}
long God::regNeuron(Neuron * n)
{
neurons.push_back(n);
cout << neurons.size() << "\n";
return neurons.size();
}
And at least, my Neuron.
//neuron.hpp
#ifndef NEURON_HPP
#define NEURON_HPP 1
#include "god.hpp" //Evil
class Neuron
{
public:
Neuron();
void setGod(God *g);
};
#endif
//neuron.cpp
#include <iostream>
#include "neuron.hpp"
#include "god.hpp"
Neuron::Neuron()
{
}
void Neuron::setGod(God *g)
{
std::cout << "Created Neuron!";
}
I hope someone can help me to find the error. It happens when I write #include "god.hpp" in neuron.hpp. I searched around three hours with Google, but I had no luck.
Kind regards
-Boris
Compiled with:
g++ -Wall -o getneurons main.cpp functions.cpp god.cpp neuron.cpp
Remove
#include "god.hpp"
and replace it with a forward declaration:
//neuron.hpp
#ifndef NEURON_HPP
#define NEURON_HPP 1
class God; //forward declaration
class Neuron
{
public:
Neuron();
void setGod(God *g);
};
#endif
Same for God.hpp:
//god.hpp
#ifndef GOD_HPP
#define GOD_HPP 1
#include <vector>
class Neuron; //forward declaration
class God
{
public:
God();
long regNeuron(Neuron * n);
private:
std::vector<Neuron*> neurons;
};
#endif
Note that you'll need the includes in your implementation files. (cpp files)
If you use pointers or references to objects as members or use that type as a return type or parameter, the full definition isn't required, so a forward declaration is enough.