Can I get polymorphic behavior without using virtual functions?

后端 未结 11 1400
栀梦
栀梦 2020-12-03 13:54

Because of my device I can\'t use virtual functions. Suppose I have:

class Base
{
    void doSomething() { }
};

class Derived : public Base
{
    void doSom         


        
11条回答
  •  广开言路
    2020-12-03 14:37

    Since virtual methods are usually implemented by means of vtables, there's no magic happening that you can't replicate in code. You could, in fact, implement your own virtual dispatch mechanism. It takes some work, both on the part of the programmer who implements the base class and the programmer who implements the derived class, but it works.

    Casting the pointer, like as suggested by ceretullis, is probably the first thing you should consider doing. But the solution I post here at least gives you the opportunity to write code that uses these classes as if your compiler supported virtual. That is, with a simple function call.

    This is a program that implements a Base class with a function that returns a string: "base", and a Derived class that returns a string: "der". The idea is to be able to support code like this:

    Base* obj = new Der;
    cout << obj->get_string();
    

    ...so that the get_string() call will return "der" even though we are calling through a Base pointer and using a compiler that doesn't support virtual.

    It works by implementing our own version of a vtable. Actually, it's not really a table. It's just a member-function pointer in the base class. In the base class' implementation of get_string(), if the member-function pointer is non-null, the function is called. If it is null, the base class implementation is executed.

    Simple, straightforward and pretty basic. This could probably be improved a lot. But it shows the basic technique.

    #include 
    #include 
    #include 
    using namespace std;
    
    class Base
    {
    public:
        typedef string (Base::*vptr_get_string)(void) const;
        Base(vptr_get_string=0);
        void set_derived_pointer(Base* derived);
    
        string get_string() const;
    
    protected:
        Base* der_ptr_;
        vptr_get_string get_string_vf_;
    };
    
    Base::Base(vptr_get_string get_string_vf)
    :   der_ptr_(0),
        get_string_vf_(get_string_vf)
    {
    }
    
    void Base::set_derived_pointer(Base* derived)
    {
        der_ptr_ = derived;
    }
    
    string Base::get_string() const
    {
        if( get_string_vf_ )
            return (der_ptr_->*get_string_vf_)();
        else
            return "base";
    }
    
    class Der : public Base
    {
    public:
        Der();
        string get_string() const;
    };
    
    Der::Der()
    :   Base(static_cast(&Der::get_string))
    {
        set_derived_pointer(this);
    }
    
    string Der::get_string() const
    {
        return "der";
    }
    
    int main()
    {
        Base* obj = new Der;
        cout << obj->get_string();
        delete obj;
    }
    

提交回复
热议问题