Alternative to c++ static virtual methods

前端 未结 12 2181
深忆病人
深忆病人 2020-12-04 21:58

In C++ is not possible to declare a static virtual function, neither cast a non-static function to a C style function pointer.

Now, I have a plain ol\' C SDK that us

12条回答
  •  半阙折子戏
    2020-12-04 22:07

    If the derived type of an object can be determined at compile time, you can use the "Curiously Recurring Template Pattern" to achieve static polymorphism. With this approach you are not limited to just overriding virtual non-static member functions. Static and non-function members are fair game. You can even override types (but the base object size can't be a function of the those types).

    #include 
    #include 
    
    struct VirtualBase {
        static const char* staticConst;
        static char* staticVar;
        static char* staticFun() { return "original static function"; }
        const char* objectConst;
        char* objectVar;
        virtual char* objectFun() { return "original object function"; }
        typedef int8_t Number;
        VirtualBase():
            objectConst("original object const"),
            objectVar("original object var")
        {}
        void virtual_dump(std::ostream& out=std::cout) {
            out << this->staticConst << std::endl;
            out << this->staticVar << std::endl;
            out << this->staticFun() << std::endl;
            out << this->objectConst << std::endl;
            out << this->objectVar << std::endl;
            out << this->objectFun() << std::endl;
            out << "sizeof(Number): " << sizeof(Number) << std::endl;
        }
    };
    const char* VirtualBase::staticConst = "original static const";
    char* VirtualBase::staticVar = "original static var";
    
    template 
    struct RecurringBase: public VirtualBase {
        void recurring_dump(std::ostream& out=std::cout) {
            out << Derived::staticConst << std::endl;
            out << Derived::staticVar << std::endl;
            out << Derived::staticFun() << std::endl;
            out << static_cast(this)->staticConst << std::endl;
            out << static_cast(this)->staticVar << std::endl;
            out << static_cast(this)->staticFun() << std::endl;
            out << static_cast(this)->objectConst << std::endl;
            out << static_cast(this)->objectVar << std::endl;
            out << static_cast(this)->objectFun() << std::endl;
            out << "sizeof(Number): " << sizeof(typename Derived::Number) << std::endl;
        }
    };
    
    struct Defaults : public RecurringBase {
    };
    
    struct Overridden : public RecurringBase {
        static const char* staticConst;
        static char* staticVar;
        static char* staticFun() { return "overridden static function"; }
        const char* objectConst;
        char* objectVar;
        char* objectFun() { return "overridden object function"; }
        typedef int64_t Number;
        Overridden():
            objectConst("overridden object const"),
            objectVar("overridden object var")
        {}
    };
    const char* Overridden::staticConst = "overridden static const";
    char* Overridden::staticVar = "overridden static var";
    
    int main()
    {
        Defaults defaults;
        Overridden overridden;
        defaults.virtual_dump(std::cout << "defaults.virtual_dump:\n");
        overridden.virtual_dump(std::cout << "overridden.virtual_dump:\n");
        defaults.recurring_dump(std::cout << "defaults.recurring_dump:\n");
        overridden.recurring_dump(std::cout << "overridden.recurring_dump:\n");
    }
    

    Here is the output:

    defaults.virtual_dump:
    original static const
    original static var
    original static function
    original object const
    original object var
    original object function
    sizeof(Number): 1
    overridden.virtual_dump:
    original static const
    original static var
    original static function
    original object const
    original object var
    overridden object function
    sizeof(Number): 1
    defaults.recurring_dump:
    original static const
    original static var
    original static function
    original static const
    original static var
    original static function
    original object const
    original object var
    original object function
    sizeof(Number): 1
    overridden.recurring_dump:
    overridden static const
    overridden static var
    overridden static function
    overridden static const
    overridden static var
    overridden static function
    overridden object const
    overridden object var
    overridden object function
    sizeof(Number): 8
    

    If the derived type cannot be determined until run-time, just use a virtual non-static member function to gather static or non-function info about the class or object.

提交回复
热议问题