代码之家  ›  专栏  ›  技术社区  ›  Eris

纯虚拟成员有什么优势吗(除了他们可能防止的人为错误)?

  •  2
  • Eris  · 技术社区  · 2 年前

    我有一堆纯虚拟成员的类,它将由派生的非抽象类填充。我得到了一个错误:

    Error   C2259   'ABC': cannot instantiate abstract class    TEMP    c:\program files (x86)\microsoft visual studio\2017\enterprise\vc\tools\msvc\14.16.27023\include\xmemory0   879 
    

    这个错误可以通过使用 stack<ABC*> 然而,堆内存访问比堆栈内存慢,因此我考虑重写基类ABC,而不使用任何纯虚拟成员。

    有没有办法创建一个类堆栈,堆栈上有纯虚拟成员?或者,也许我对使用堆过于偏执?该类(在原始代码中)将被频繁访问。

    #include <iostream>
    #include <stack>
    
    class ABC {
    public:
        ABC(int& a) : m_a(a) {}
        ~ABC() {}
        virtual void do_something() = 0;
        int m_a;
    };
    
    class DEF : public ABC {
    public:
        DEF(int& a) : ABC(a) {}
        void do_something() override;
        ~DEF() {}
    };
    
    void DEF::do_something() {
        std::cout << "Hi!\n";
    }
    
    int main(int argc, char* argv[]) {
        int x = 123;
        std::stack<ABC> s;
    
        s.push(DEF(x));
    }
    
    2 回复  |  直到 2 年前
        1
  •  1
  •   Vlad from Moscow    2 年前

    在这次通话中

    s.push(DEF(x));
    

    类型的临时对象 DEF ABC 因此,如果要调用虚函数,则将调用ABC类的虚函数。

    这是你的最新计划。

    #include <iostream>
    #include <stack>
    
    class ABC {
    public:
        ABC(int& a) : m_a(a) {}
        ~ABC() {}
        virtual void do_something() 
        {
            std::cout << "Bye!\n";
        };
        int m_a;
    };
    
    class DEF : public ABC {
    public:
        DEF(int& a) : ABC(a) {}
        void do_something() override;
        ~DEF() {}
    };
    
    void DEF::do_something() {
        std::cout << "Hi!\n";
    }
    
    int main()
    {
        int x = 123;
        std::stack<ABC> s;
    
        s.push(DEF(x));
    
        s.top().do_something();
    }
    

    程序输出为

    Bye!
    

    请注意,您需要使析构函数虚拟化。你可以在基类中写

    virtual ~ABC() = default;
    
        2
  •  0
  •   SoronelHaetir    2 年前

    你根本不可能拥有一个包含虚拟成员的对象的容器(以堆栈为例)(纯或非纯)并保持动态行为。您可以拥有指向此类对象的指针容器并维护动态行为,但不能维护此类对象本身。