使用带有转发类的析构函数

Posted

技术标签:

【中文标题】使用带有转发类的析构函数【英文标题】:Use a destructor with forwarded classes 【发布时间】:2016-02-03 04:16:56 【问题描述】:

我的一个项目有问题。两个班级互相使用,但我解决了这个问题。 问题是使用析构函数。这是错误日志:

location.cpp: In destructor ‘Location::~Location()’:
location.cpp:13:16: warning: possible problem detected in invocation of delete operator: [-Wdelete-incomplete]
         delete it;
                ^
location.cpp:13:16: warning: invalid use of incomplete type ‘class Link’
In file included from location.cpp:1:0:
location.hpp:10:7: note: forward declaration of ‘class Link’
 class Link;
       ^
location.cpp:13:16: note: neither the destructor nor the class-specific operator delete will be called, even if they are declared when the class is defined
         delete it;
                ^
g++ -c -Wall -std=c++11 -g -c link.cpp
link.cpp: In destructor ‘Link::~Link()’:
link.cpp:8:12: warning: possible problem detected in invocation of delete operator: [-Wdelete-incomplete]
     delete src;
            ^
link.cpp:8:12: warning: invalid use of incomplete type ‘class Location’
In file included from link.cpp:1:0:
link.hpp:4:7: note: forward declaration of ‘class Location’
 class Location;
       ^
link.cpp:8:12: note: neither the destructor nor the class-specific operator delete will be called, even if they are declared when the class is defined
     delete src;
            ^
link.cpp:9:12: warning: possible problem detected in invocation of delete operator: [-Wdelete-incomplete]
     delete dst;
            ^
link.cpp:9:12: warning: invalid use of incomplete type ‘class Location’
In file included from link.cpp:1:0:
link.hpp:4:7: note: forward declaration of ‘class Location’
 class Location;
       ^
link.cpp:9:12: note: neither the destructor nor the class-specific operator delete will be called, even if they are declared when the class is defined
     delete dst;
            ^
link.cpp: In member function ‘double Link::length() const’:
link.cpp:14:15: error: invalid use of incomplete type ‘class Location’
     return src->distanceTo(dst);
               ^
In file included from link.cpp:1:0:
link.hpp:4:7: note: forward declaration of ‘class Location’
 class Location;
       ^
Makefile:28: recipe for target 'link.o' failed
make: *** [link.o] Error 1
make: *** Waiting for unfinished jobs....

看来析构函数不能互相调用,Link::length()函数有问题。

代码如下:

location.hpp

#ifndef LOCATION
#define LOCATION

#include <vector>
#include <string>
#include <iterator>
#include <algorithm>
#include <memory>

class Link;

class Location 
    public:
        Location(std::string _name, double _x, double _y);
        ~Location();

        static int next_id;
        int id ++next_id ;
        std::string name;
        double x, y;
        std::vector<Link*> links;

        std::string toString() const;
        int compareTo( const Location *l ) const;
        double distanceTo( const Location *l ) const;
;

#endif

位置.cpp

#ifndef LOCATION
#define LOCATION

#include <vector>
#include <string>
#include <iterator>
#include <algorithm>
#include <memory>

class Link;

class Location 
    public:
        Location(std::string _name, double _x, double _y);
        ~Location();

        static int next_id;
        int id ++next_id ;
        std::string name;
        double x, y;
        std::vector<Link*> links;

        std::string toString() const;
        int compareTo( const Location *l ) const;
        double distanceTo( const Location *l ) const;
;

#endif

链接.hpp

#ifndef LINK
#define LINK

class Location;

class Link 
    public:
        Link(Location *s, Location *d);
        ~Link();

        Location *src;
        Location *dst;

        double length() const;
;

#endif

链接.cpp

#include "location.hpp"
#include <cmath>

int Location::next_id 1 ;

Location::Location(std::string _name, double _x, double _y) :
    name(_name), x(_x), y(_y)


Location::~Location()

    for(auto &it : links)
        delete it;

    links.clear();


std::string Location::toString() const

    return name;


int Location::compareTo( const Location *l ) const

    return id - l->id;


double Location::distanceTo( const Location *l ) const

    double dx = x - l->x;
    double dy = y - l->y;
    return sqrt(dx*dx + dy*dy);

谢谢!

【问题讨论】:

【参考方案1】:

您需要在实现~Location 的文件中包含Link 的头文件。

最好的线索在警告信息中:

警告:不完整类型“类链接”的使用无效

你遇到的问题是可以转发声明一个类来防止循环依赖,但是一旦你真正使用它(即删除Link时),你的源文件需要知道实际的类声明。

【讨论】:

以上是关于使用带有转发类的析构函数的主要内容,如果未能解决你的问题,请参考以下文章

虚析构函数

基类的析构函数写成virtual虚析构函数

C++ 设置基类的析构函数为虚函数

C++中,子类会继承父类的虚函数表!对于父类的析构函数(虚函数) 也会继承吗?

在一个派生类对象结束其生命周期时析构函数的调用顺序

在类的析构函数中删除数组