每个派生类的 C++ 分离静态字段

标签 c++ inheritance interface static crtp

考虑了很长一段时间我的问题的解决方案,当我没有其他想法只能在这里问的时候,我终于明白了。

我有以下问题。

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

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

但是我当然不能简单地继承静态成员并期望它们在每个子类中都是唯一的。我试图使用 Curiously Recurring Template Pattern (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);
}

最佳答案

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

相反,您可以使用 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;
}

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

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

希望对您有所帮助。

关于每个派生类的 C++ 分离静态字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45423024/

相关文章:

c++ - 使用yaml-cpp解析YAML文件

c++ - 如何在C++中继承类?

swift - 使用 SKSpriteNode 的属性作为子类

objective-c - 将实例变量放在没有 getter 和 setter 的 .h 中有什么用(即没有人可以设置或获取它)?

c# - C++ 异常与 C# 异常

c++ - 显示基于 1 种类型的结构 vector 值

java - 学习接口(interface)和层次结构,在哪里放置某些变量和方法?

python - Python中抽象类和接口(interface)的区别

c# - 界面是否即将过时?

c++ - 错误 LNK2019 : unresolved external symbol "extern "C"what is this error?