在头文件.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*/)
我知道,抽象方法可以在基类中定义,如下所示,然后在Derived类中定义它们:
在头文件.hpp中:
class Base{
public:
virtual /*Some Return Type*/ func(/*Some Datatype*/) const = 0;
}
但问题是虚方法需要对象实例化,这不是我想要的。我想在不创建对象的情况下调用该方法。如果允许使用虚拟静态方法,那么它们就可以达到目的。
我能想到的唯一选择是在头文件中的所有Derived类中声明函数func()
并将其从Base类中删除。有没有其他方法可以做到这一点?因此声明在Base类中只有一次,并且所有Derived类只需要定义它们,而不是重新声明?
答案 0 :(得分: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() ) ...
(我们已经建立了唯一可以获得的规则 类的名称是使用这些函数之一。那 有效地内化了类的名称,并允许 简单的指针比较工作。在我们的系统上 那么,这很重要。)
答案 1 :(得分:1)
你可以这样做有点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:非常奇怪,你不想在派生类中声明这个函数,因为当你使用虚函数时,你应该在派生类中声明它们
答案 2 :(得分: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或类型特征。