简体   繁体   English

C ++前向声明和析构函数

[英]C++ Forward declaration and destructor

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 : 这是我的第一个类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: HEre是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: 这是另一个Character.h类:

#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. 所以当我的程序结束时,我调用Header的函数“cleanUp()”,给它一个指向Characters的指针。 Every pointer should then be deleted through the Character's destructor ~Character(); 然后应该通过Character的析构函数~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 ); 是的,这就是(草案)标准所说的( §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. 要修复它,只需在header.cpp #include "Character.h" ,然后再调用delete以允许完全声明类型。

When you use class MyClass; 当你使用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. 要转发声明你的类,这只声明名为MyClass的东西是一个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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM