C++ 为什么多态类型会出现错误和清除问题? #包括 #包括 #包括 #包括 类基{}; 类derived1:公共基 { 公众: 无符号短n; derived1() { n=2; } }; 类derived2:公共基{}; void main() { //方式1 { std::载体a1; std::载体a2; 地图b; a1.向后推(derived1()); b[“abc”]=&a1.at(0); std::coutn

C++ 为什么多态类型会出现错误和清除问题? #包括 #包括 #包括 #包括 类基{}; 类derived1:公共基 { 公众: 无符号短n; derived1() { n=2; } }; 类derived2:公共基{}; void main() { //方式1 { std::载体a1; std::载体a2; 地图b; a1.向后推(derived1()); b[“abc”]=&a1.at(0); std::coutn,c++,types,stdmap,polymorphism,C++,Types,Stdmap,Polymorphism,要使Base成为多态类型,您需要至少为其提供一个虚拟函数。在这种情况下,最简单的是析构函数: #include <iostream> #include <string> #include <map> #include <vector> class base {}; class derived1 : public base { public: unsigned short n; derived1()

要使
Base
成为多态类型,您需要至少为其提供一个虚拟函数。在这种情况下,最简单的是析构函数:

#include <iostream>
#include <string>
#include <map>
#include <vector>

class base {};
class derived1 : public base
{
    public:
        unsigned short n;
        derived1()
        {
            n = 2;
        }
};
class derived2 : public base {};

void main()
{
    // way 1
    {
        std::vector<derived1> a1;
        std::vector<derived2> a2;
        std::map<std::string, base*> b;
        a1.push_back(derived1());
        b["abc"] = &a1.at(0);
        std::cout<<(dynamic_cast<derived1*>(b.find("abc")->second))->n<<std::endl;
    }

    // way 2
    {
        std::map<std::string, base*> b;
        b["abc"] = new derived1();
        std::cout<<dynamic_cast<derived1*>(b.find("abc")->second)->n<<std::endl;
        delete dynamic_cast<derived1*>(b.find("abc")->second);
    }
}

关于您关于清理的问题:
从技术上讲,这两种方式都存在一些未定义的行为,因为映射引用的对象在指针从映射中移除之前被销毁。这导致映射在销毁时包含无效指针,从而导致未定义的行为。
出于实际目的,这不会导致任何已知编译器出现任何问题

否则,您将正确地清理一切。
但在第二种方式中,您可以进行简化。当
Base
有一个虚拟析构函数时,您可以这样做

class Base {
public:
  virtual ~Base() { }
};

没有动态强制转换。

main
返回类型不应该是
void
。一般建议:不要存储指向向量元素的指针!一旦发生重新分配,这些指针就会无效!唯一的例外是:如果您可以保证不再发生重新分配,并且您不删除元素,这样指针将point超出了当前向量大小。感谢你写得很好的答案。我很惊讶,也很高兴我能以方式2简化删除行。这样我就可以清理指针另一侧的对象,我不知道指向的对象类型的所有信息。悬空指针不会导致未定义的行为,除非它们被解除引用。
映射
不会在其析构函数或任何其他方法中解除对其
基*
指针的引用。@aschepper:悬空指针也会导致UB(尽管通常有良性影响)如果在发生“左值到右值转换”的上下文中使用它们。当
映射
破坏其内容时,就会发生这种转换。
delete b.find("abc")->second;