1

在头文件 .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()在头文件的所有派生类中声明该函数,并将其从基类中删除。有没有其他方法可以做到这一点?这样声明在基类中只有一次,所有派生类只需要定义它们,而不是重新声明?

4

3 回答 3

4

在没有对象的情况下调用虚函数是一种矛盾,因为分辨率取决于对象的类型。在某些情况下,您可能需要根据对象的类型调用相同的函数,或者在没有对象的情况下显式指定类。这很容易通过使用两个函数来处理,一个是静态的,一个是虚拟的。(通常,虚拟的只会转发到静态的。)

编辑:

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

#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() ) ...

(我们已经建立了一个规则,即获得类名的唯一方法是使用其中一个函数。这有效地内化了类名,并允许简单的指针比较工作。在我们正在研究的系统上那么,这很重要。)

于 2013-04-04T15:21:26.327 回答
3

你可以这样做有点hacky =)

//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:很奇怪,你不想在派生类中声明这个函数,因为当你使用虚函数时,你应该在派生类中声明它们

于 2013-04-04T15:31:31.723 回答
1

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

  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 或 type-traits 以获得替代方法。

于 2013-04-04T18:04:39.393 回答