std::map、多态和删除

发布于 2024-11-16 19:20:41 字数 1624 浏览 3 评论 0原文

我在使用 C++ 映射存储指向基类和某些派生类的指针时遇到问题。

让我用一个相当长但简单的代码来解释:

#include <map>
#include <iostream>

struct foo{ int dummy[4]; };
struct bar{ int additionnal[4]; };

class Base
{
private:
    struct foo *_internal_structure;
public:
    Base() { _internal_structure = new struct foo; }
   ~Base()
   {
        delete _internal_structure;
        std::cout << "Base DTOR\n";
   }
};

class Derived: public Base
{
private:
    struct bar *_additional_structure;
public:
    Derived() { _additional_structure = new struct bar; }
   ~Derived()
   {
        delete _additional_structure;
        std::cout << "Derived DTOR\n";
   }
};


int main(int argc, char *argv[])
{
    std::map<int, Base*> my_map;
    Base *to_add = new Base();
    Derived *derived_to_add = new Derived();
    my_map[1] = to_add;
    my_map[2] = derived_to_add; // works, derived class, but object gets sliced

    /// clear hash map ///
    std::map<int, Base*>::const_iterator iter;
    for(iter = my_map.begin(); iter != my_map.end(); ++iter)
    {
        delete (*iter).second;
    }

    return 0;
}

运行结果:

Base DTOR
Base DTOR

所以,事情是,当我将 Derived 类指针插入到我的映射中时,底层对象被视为 Base< /em> 类;因此调用的析构函数是基类的析构函数,而不是派生类的析构函数。 Valgrind 确认我每次都会丢失 16 个字节。

另外,我无法使用Boost的shared_ptr我在这里看到了一些提及),并且我使用的嵌入式架构不支持 C++ 异常和 RTTI (在我的例子中,这会导致一些未对齐的访问和其他不良情况)东西)编辑:不相关)。

你知道我该如何解决这个问题吗?

I have a problem using a C++ map to store pointers to a base class and some derived class.

Let me explain by a rather long but simple code:

#include <map>
#include <iostream>

struct foo{ int dummy[4]; };
struct bar{ int additionnal[4]; };

class Base
{
private:
    struct foo *_internal_structure;
public:
    Base() { _internal_structure = new struct foo; }
   ~Base()
   {
        delete _internal_structure;
        std::cout << "Base DTOR\n";
   }
};

class Derived: public Base
{
private:
    struct bar *_additional_structure;
public:
    Derived() { _additional_structure = new struct bar; }
   ~Derived()
   {
        delete _additional_structure;
        std::cout << "Derived DTOR\n";
   }
};


int main(int argc, char *argv[])
{
    std::map<int, Base*> my_map;
    Base *to_add = new Base();
    Derived *derived_to_add = new Derived();
    my_map[1] = to_add;
    my_map[2] = derived_to_add; // works, derived class, but object gets sliced

    /// clear hash map ///
    std::map<int, Base*>::const_iterator iter;
    for(iter = my_map.begin(); iter != my_map.end(); ++iter)
    {
        delete (*iter).second;
    }

    return 0;
}

Result when run:

Base DTOR
Base DTOR

So, thing is, when I insert a Derived class pointer into my map, the underlying object is considered as a Base class; so the destructor called is the one of the Base class, and not the Derived class. Valgrind confirms me that I loose 16 bytes every time.

Also, I can't use Boost's shared_ptr (I saw some mentions of it here), and the embedded architecture I use doesn't support C++ exceptions and RTTI (which in my case, causes some unaligned accesses and other bad stuff)(edit: not related).

Do you know how I can fix this behavior?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

新人笑 2024-11-23 19:20:41

你的虚拟析构函数在哪里???!!!

阅读本文,并且永远忘记。真的,你刚刚违反了 10 条 C++ 戒律之一......:))

Where is your virtual destructor???!!!

Read this, and never forget. Really, you have just broken one of the 10 C++ commandments... :))

作死小能手 2024-11-23 19:20:41

任何基类中的析构函数都应该是虚拟

否则,在通过指向其基类的指针引用子类的情况下,不可能在运行时确定实际应该调用哪些析构函数。

Your destructor in any base class should be virtual.

Otherwise it's impossible at runtime to determine what destructor(s) should actually be called, in the case where subclasses are referenced through a pointer to their base class.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文