2017-07-31 27 views
3

长时间以来,我一直在考虑解决我的问题,而当我没有其他想法时,我终于明白了,只是在此问一问。C++每个派生类的分隔静态字段

我有以下问题。

简短版本。如何从基类继承静态字段,但在每个派生类中使其唯一,并保留将这些类转发到父类的可能性?

长版。我需要为一组类创建一些基本接口。每个类都需要有一个静态字段和一个静态方法。但我希望能够将所有这些类作为参数传递给一个使用这些静态成员的通用函数。所以我在考虑从一个基类继承它们。

但我当然不能简单地继承静态成员,并期望它们在每个子类中都是唯一的。我试图使用好奇的循环模板模式(CRTP),但它迫使我制作这个通用函数模板,并在每次调用时直接给它起类名。这对我不好。

此外,我使用CRTP工作时遇到问题时,使用多个级别的继承(即当我想从派生从这个模板基类的类派生多一个类)。有什么方法可以实现我需要的吗?

我知道类似的问题已经被提出,但大多数作者对CRTP感到满意。对我来说,它似乎不像解决方案够好。

//pseudo-code for what I need, doesn't work of course 
class Base { 
public: 
    static int x; 
    static int GetX() {return x;} 
} 

class Derived : public Base {}; 
class NextDerived : public Derived {}; 
class NextDerived2 : public Derived {}; 

void Foo(Base& a) {a.x = 10;} 

int main { 
    NextDerived d; 
    NextDerived2 d2; 
    Foo(d); 
    Foo(d2); //both Foos modify different static variables 
} 

//CRTP attempt 
template <class C> 
class Base { 
public: 
    static int x; 
    static int GetX() {return x} 
}; 

class Derived : public Base<Derived> {}; 
int Derived::x = 0; 

template <class C> 
void Foo(Base<C>& b) { 
    b.x = 10; 
    return; 
}; 

int main() { 
    Derived d; 

    Foo<Derived>(d); 
} 
+0

这听起来像一个模板的工作。 –

+1

CRTP是解决您的问题的方案。我没有看到任何其他方式为每个子类使用不同的静态变量。 CRTP解决方案有什么问题? –

+0

为什么写'Foo (d);'? 'Foo(d);'应该很好。 –

回答

1

请记住,还必须定义静态变量。因此,对于每个需要单独静态变量的派生类型,您都需要定义它。

相反,您可以使用std::map和type-id哈希来做类似的事情,而不需要混淆基类。此外,这可以让你有使用任何类型,例如:

#include <iostream> 
#include <map> 
#define out(v) std::cout << v << std::endl 

static std::map<std::size_t, int> ExsAndOhs; 

template < typename T > 
static std::size_t type_id() // in case you don't want RTTI on 
{ 
    static char tid; 
    return reinterpret_cast<std::size_t>(&tid); 
} 

template < typename T > 
void Foo(int _x) { ExsAndOhs[type_id<T>()] = _x; } 

template < typename T > 
void Foo(T& obj, int _x) { ExsAndOhs[type_id<T>()] = _x; } 

template < typename T > 
void Print() { out(ExsAndOhs[type_id<T>()]); } 

template < typename T > 
void Print(T& obj) { out(ExsAndOhs[type_id<T>()]); } 


class Base {}; 
class Derived : public Base {}; 
class D2 : public Base {}; 

int main(int argc, char* argv[]) 
{ 
    // using explicit templates 
    Foo<Base>(100); 
    Foo<Derived>(10); 
    Foo<D2>(42); 
    Foo<long>(65535); 
    Foo<int>(1955); 
    Print<Base>(); 
    Print<Derived>(); 
    Print<D2>(); 
    Print<long>(); 
    Print<int>(); 


    Base b; 
    Derived d; 
    D2 d2; 
    int x = 1; 
    long y = 1; 
    // using template deduction 
    Foo(b, 10); 
    Foo(d, 42); 
    Foo(d2, 100); 
    Print(b); 
    Print(d); 
    Print(d2); 
    Print(x); // still prints 1955 
    Print(y); // still prints 65535 

    return 0; 
} 

这也避免了需要声明的每个派生类的静态成员。

对于您的特定用例,这可能不是一个好的解决方案,但它是实现您要求的另一种选择。

希望能有所帮助。

0

这种CRTP风格适合你吗?

#include <iostream> 

using namespace std; 

template<class T> 
class Base { 
public: 
    static int x; 
    static int GetX() {return x;} 
}; 

template<class T> 
class Derived : public Base <Derived<T> >{}; 
class NextDerived : public Derived<NextDerived> {}; 
class NextDerived2 : public Derived<NextDerived2> {}; 

static int count = 0; 

template<class T> int Base<T>::x = 0; 


template<class T> 
void Foo(Base<Derived<T> >& a) { 
    a.x = count++; 
}; 

int main() { 
    NextDerived d; 
    NextDerived2 d2; 
    Foo(d); 
    Foo(d2); 

    cout << d.GetX() << " " << d2.GetX() << endl; 
    return 0; 
}