c++中虚拟静态函数的替代方案

Alternative to virtual static functions in c++?

本文关键字:方案 静态函数 虚拟 c++      更新时间:2023-10-16

在头文件。hpp:

  class Base{
        public:
              static /*Some Return Type*/ func(/*Some Datatype*/);
  }    
  class Derived1 public Base{
        public: 
               Derived1();
               ~Derived1();
  }
  class Derived1 public Base{
        public: 
               Derived2();
               ~Derived2();
  }
在cpp文件中。cpp:
  /*Some Return Type*/ Derived1::func(/*Some Datatype*/){
  }
  /*Some Return Type*/ Derived2::func(/*Some Datatype*/){
  }

这显然是失败的,因为没有办法在子类中重写静态方法。但是如何获得上述功能呢?

我必须这样称呼:

  /*Some Return Type*/ result = Derived1::func(/*Some Datatype*/)
  /*Some Return Type*/ result = Derived2::func(/*Some Datatype*/)
我知道,抽象方法可以像下面这样在基类中定义,然后在派生类中定义:

在头文件。hpp:

  class Base{
        public:
              virtual /*Some Return Type*/ func(/*Some Datatype*/) const = 0;
  }  

但是问题是虚方法需要对象实例化,这不是我想要的。我想在不创建对象的情况下调用方法。如果允许使用虚拟静态方法,它们就可以达到目的。

我能想到的唯一替代方案是在头文件中的所有派生类中声明函数func(),并从基类中删除它。有没有别的方法可以做这件事?所以声明只在基类中一次,所有派生类只需要定义它们,而不需要重新声明?

调用不带对象的虚函数是逆向的,因为分辨率取决于对象的类型。您是否需要调用相同的函数依赖于对象的类型,或者指定类显式地,不带对象。这很容易通过使用两个函数,一个是静态的,一个是虚函数。(通常情况下,虚拟的只会转发给静态的)

编辑:

一个简单的例子(来自实际代码):

#define DECLARE_CLASS_NAME(className)                               
    static char className() { return STRINGIZE(className); }        
    virtual char* getClassName() { return className(); }
class Base
{
public:
    DECLARE_CLASS_NAME(Base);
    //  ...
};
class Derived : public Base
{
public:
    DECLARE_CLASS_NAME(Derived);
    //  ...
};

等等,在所有的派生类中。这是用来获取用于序列化的类型名称,例如:

std::string typeName = pObj->getClassName();

以及作为原始RTTI(这是大约20年前):

if ( pObj->getClassName() == Derived::className() ) ...

)我们已经建立了一个规则,只有这样你才能获得类的名称是通过使用这些函数之一来确定的。那有效地内部化了类的名称,并允许简单的指针比较工作。在我们的系统上这一点很重要)

你可以做得有点粗糙=)

//header file
template<class T>
struct base_t
{
   static void do_smth();
};
struct derived1_t : base_t<derived1_t>
{
};
struct derived2_t : base_t<derived2_t>
{
};
//cpp file
void base_t<derived1_t>::do_smth() // `note base_t<derived1_t>::` instead of `derived1_t::`
{
   std::cout << "aaa" << std::endl;
}

PS:很奇怪,你不想在派生类中声明这个函数,因为当你使用虚函数时,你应该在派生类

中声明它们

一种可能性是只在派生类中定义它们:

  struct  Base
  {
      // nothing
  };
  struct Derived1 : public Base
  {
      static void func() { /*...*/ }
  };
  struct Derived2 : public Base
  {
      static void func() { /*...*/ }
  };

这允许你调用:

Derived1::foo();
Derived2::foo();

为基类型调用它,并期望编译器找出你指的是哪个子类型不能工作:

// How will the compiler know to choose 
// between Derived1:: func or Derived2:: func ?
Base::func(); 

您可能需要查看CRTP或类型特征来寻找替代方法。