Home  >  Q&A  >  body text

c++ - 如何改写一个template class,该类含有static function,使得对外API调用接口不改变?

由于担心中文翻译产生歧义,附上英文原题目:Rewrite template classes to use inheritance without changing the calling environment which required a static function call, but static functions can't be virtual. 英文原题描叙地址

我感觉题目大概意思是,需要改写或更新一个服务端的class,使得客户端调用相关API的时候,不需要修改接口。这里我只想到了用工厂模式来解决,当然不确定对不对。另外,static function是不能够virtual,所以继承的时候,静态函数重写(overriden)是不允许,有没有方式解决这个问题?

总的来说,我觉得此题考点包含三个:

  1. Code maintenance in server side

  2. Design pattern, mainly for factory method

  3. Any trick to overide static function in class inheritance

当然我不确定对题目的理解有没有错误。其实我不是很确定题目是想问,用继承的方式来重新修改这个class?还是重新修改这个类,这个类被其它子类继承了?

我目前还没有找到最佳答案。所以我先给出当前我能想到的答案。欢迎大家的补充和修正。万分感谢THX!!

The original code in server side:

#include<iostream>

using namespace std;

template<class T>
class Base
{
    public:
        Base(){}
        Base(T B):m_B(B){}
        virtual ~Base(){}
        
        // Static method
        static void speak()
        {
            cout << "I am Base class" << endl;
        }
    
    private:
        T m_B;
    
};


template<class T>
class Derived: public Base<T>
{
    public:
        Derived(){}
        Derived(T B, T D): Base<T>(B), m_D(D){}
        ~Derived(){}
        
        // Static method
        static void speak()
        {
            cout << "I am Derived class" << endl;
        }
    
    private:
        T m_D;
    
};

The calling environment in client side:

int main(int argc, char* argv[])
{
    Base<int> *bPtr = new Derived<int>(5, 10);
    bPtr->speak();
    delete bPtr;
    return 0;
}

Output:

I am Base class

(obviously no overrding for static function)

////////////////////////////////////////////////////////////////////////////////

My rewrote code in server side:

#include<iostream>

using namespace std;

template<class T>
class Base
{
    public:
        Base(){}
        Base(T B):m_B(B){}
        virtual ~Base(){}
        
        // Static method
        static void speak()
        {
            cout << "I am Base class" << endl;
        }
        // Non-static method
        virtual void call_speak()
        {
            speak();    
        }     
    private:
        T m_B;
    
};


template<class T>
class Derived: public Base<T>
{
    public:
        Derived(){}
        Derived(T B, T D): Base<T>(B), m_D(D){}
        ~Derived(){}
        
        // Static method
        static void speak()
        {
            cout << "I am Derived class" << endl;
        }
        // Non-static method
        void call_speak()
        {
            speak();    
        }     
    private:
        T m_D;
    
};

template<class T>
class Factory
{
    public:
        // Return a base instance
        static Base<T>* getInstance(T B)
        {
            Base<T> *bPtr = new Base<T>(B);
            return bPtr;
        }
        
        // Return a derived instance
        static Base<T>* getInstance(T B, T D)
        {
            Base<T> *bPtr = new Derived<T>(B, D);
            return bPtr;
        }
};

The calling environment in client side:

int main(int argc, char* argv[])
{
    Base<int> *bPtr = Factory<int>::getInstance(5, 10);
    bPtr->speak();
    bPtr->call_speak();
    delete bPtr;
    return 0;
}

Output:

I am Base class

I am Derived class

主要修改:

  1. 使用了工厂模式,把产生对象的过程隐藏起来。

  2. 用虚非静态函数的方式重新封装静态函数。

黄舟黄舟2765 days ago634

reply all(1)I'll reply

  • 怪我咯

    怪我咯2017-04-17 12:10:27

    After trying it, I feel that the questioner’s understanding of the topic is wrong.
    My understanding of the topic:

    without changing the calling environment
    means not changing the calling environment, that is, the main function in the question cannot be modified, and your solution modifies the main function.

    The following is my summary of the topic:

    use inheritance

    一定要使用继承。

    required a static function call

    说的是speak一定要是一个static函数。

    without changing the calling environment

    不修改main函数
    

    Under these three conditions, the only solution I can think of is class template specialization.
    I solved the problem using template specialization, but one of the requirements in the question was not met, which is Rewrite template classes.
    My method does not modify any classes, but only adds two new specialized classes, and the speak seems to be virtual.
    Here is my solution

    template<>
    class Base<int>
    {
        public:
            Base(){}
            Base(int B):m_B(B){}
            virtual ~Base(){}
            
            virtual void speak()
            {
                cout << "I am Base class" << endl;
            }
        private:
            int m_B;
        
    };
    
      template<>
    class Derived<int>: public Base<int>
    {
        public:
            Derived(){}
            Derived(int B, int D): Base<int>(B), m_D(D){}
            ~Derived(){}
            
            // Static method
            virtual void speak()
            {
                cout << "I am Derived class" << endl;
            }
        
        private:
            int m_D;
        
    };

    reply
    0
  • Cancelreply