这是可能的!
但具体来说,我们需要缩小范围。人们经常想要某种“静态虚函数”,因为需要复制代码才能通过静态调用“SomeDerivedClass :: myfunction()”和多态调用“base_class_pointer-> myfunction()”来调用相同的函数。允许这种功能的“合法”方法是复制函数定义:
class Object
{
public:
static string getTypeInformationStatic() { return "base class";}
virtual string getTypeInformation() { return getTypeInformationStatic(); }
};
class Foo: public Object
{
public:
static string getTypeInformationStatic() { return "derived class";}
virtual string getTypeInformation() { return getTypeInformationStatic(); }
};
如果基类有大量静态函数,派生类需要覆盖每一个函数,但是忘记为虚函数提供重复定义会怎么样呢?没错,在运行时我们将得到一些奇怪的错误,这很难追踪。因为代码的重复是一件坏事。下面尝试解决这个问题(我想预先说明的是,它完全是类型安全的,不含任何像typeid或dynamic_cast这样的黑魔法 :))。
所以,我们希望每个派生类仅提供一个getTypeInformation()的定义,而且很明显它必须是一个
静态函数的定义,因为如果getTypeInformation()是虚函数,就无法调用"SomeDerivedClass::getTypeInformation()"。我们如何通过指向基类的指针调用派生类的静态函数呢?使用vtable是不可能的,因为vtable只存储指向虚函数的指针,既然我们决定不使用虚函数,我们就不能修改vtable以达到我们的目的。因此,为了能够通过指向基类的指针访问派生类的静态函数,我们必须以某种方式在其基类中存储对象的类型。一种方法是使用“奇异递归模板模式”使基类成为模板,但在这里不适用,我们将使用一种称为“类型抹消”的技术:
class TypeKeeper
{
public:
virtual string getTypeInformation() = 0;
};
template<class T>
class TypeKeeperImpl: public TypeKeeper
{
public:
virtual string getTypeInformation() { return T::getTypeInformationStatic(); }
};
现在我们可以使用变量“keeper”在基类“Object”中存储对象的类型:
class Object
{
public:
Object(){}
boost::scoped_ptr<TypeKeeper> keeper;
string getTypeInformation() const
{ return keeper? keeper->getTypeInformation(): string("base class"); }
};
在派生类中,keeper必须在构造函数中初始化:
class Foo: public Object
{
public:
Foo() { keeper.reset(new TypeKeeperImpl<Foo>()); }
static string getTypeInformationStatic()
{ return "class for proving static virtual functions concept"; }
};
让我们添加语法糖:
template<class T>
void override_static_functions(T* t)
{ t->keeper.reset(new TypeKeeperImpl<T>()); }
现在后代的声明看起来像这样:
class Foo: public Object
{
public:
Foo() { OVERRIDE_STATIC_FUNCTIONS; }
static string getTypeInformationStatic()
{ return "class for proving static virtual functions concept"; }
};
class Bar: public Foo
{
public:
Bar() { OVERRIDE_STATIC_FUNCTIONS; }
static string getTypeInformationStatic()
{ return "another class for the same reason"; }
};
用法:
Object* obj = new Foo();
cout << obj->getTypeInformation() << endl;
obj = new Bar();
cout << obj->getTypeInformation() << endl;
Foo* foo = new Bar();
cout << foo->getTypeInformation() << endl;
Foo::getTypeInformation();
Foo::getTypeInformationStatic();
Bar::getTypeInformationStatic();
优点:
- 减少代码重复(但我们必须在每个构造函数中调用OVERRIDE_STATIC_FUNCTIONS)
缺点:
- 在每个构造函数中调用OVERRIDE_STATIC_FUNCTIONS
- 内存和性能开销
- 增加了复杂性
未解决的问题:
1) 静态函数和虚拟函数有不同的名称,如何解决歧义?
class Foo
{
public:
static void f(bool f=true) { cout << "static";}
virtual void f() { cout << "virtual";}
};
Foo::f();
ptr_to_foo->f();
2) 如何在每个构造函数中隐式调用OVERRIDE_STATIC_FUNCTIONS?