【问题标题】:C++ : Initializing base class constant static variable with different value in derived class?C++:在派生类中用不同的值初始化基类常量静态变量?
【发布时间】:2011-02-10 13:02:09
【问题描述】:

我有一个带有常量静态变量 a 的基类 A。我需要 B 类的实例对静态变量 a 具有不同的值。如何实现这一点,最好使用静态初始化?

class A {
public:
    static const int a;
};
const int A::a = 1;

class B : public A {
    // ???
    // How to set *a* to a value specific to instances of class B ?
};

【问题讨论】:

    标签: c++ static class-variables


    【解决方案1】:

    也许我们可以尝试如下方式:: 下面的好处是你不必多次编写代码,但实际生成的代码可能会很大。

    #include <iostream>
    
    using namespace std;
    template <int t>
    class Fighters {
    protected :
        static const double Fattack;
        double Fhealth;
        static const double Fdamage;
        static int count;
    public :
        Fighters(double Fh) : Fhealth(Fh) { }
        void FighterAttacked(double damage) {
            Fhealth -= damage;
        }
        double getHealth()
        {
            return Fhealth;
        }
    
        static int getCount() 
        {
            //cout << count << endl;
            return count;
        }
    };
    
    const double Fighters<1>::Fdamage = 200.0f;
    const double Fighters<1>::Fattack = 0.6f;
    int Fighters<1>::count = 0;
    
    class Humans : public Fighters<1> {
    public :
        Humans(double Fh = 250) : Fighters<1>(Fh) { count++; }
    };
    
    const double Fighters<2>::Fdamage = 40.0f;
    const double Fighters<2>::Fattack = 0.4f;
    int Fighters<2>::count = 0;
    
    class Skeletons : public Fighters<2> {
    public :
        Skeletons(double Fh = 50) : Fighters<2>(Fh) { count++; }
    };
    
    int main()
    {
    
        Humans h[100];
        Skeletons s[300];
    
        cout << Humans::getCount() << endl;
        cout << Skeletons::getCount() << endl;
    
        return 0;
    }
    

    这是我的其他代码示例的一部分.. 不介意许多其他数据,但可以看到概念。

    【讨论】:

      【解决方案2】:

      您可以使用 Curiously recurring template pattern 执行此操作(不过,您将不得不失去 const)。

      template <typename T>
      class A {
      public:
          static int a;
      };
      
      template <typename T>
      int A<T>::a = 0;
      
      class B : public A<B> {
          struct helper { // change the value for A<B>::a
              helper() { A<B>::a = 42; }
          };
          static helper h;
      };
      B::helper B::h;
      

      【讨论】:

      • 这会创建一个不同的静态变量。
      • @Neil,当然可以,一个变量不能有两个不同的值。
      • 大卫罗德里格斯的提议比较简单。在这里使用模板有什么好处?
      • @chmike,我不确定我的方式有没有好处(我在看到大卫之前写的)。大卫的方法为 B::a 创建了一个不同的变量,它恰好具有相同的名称,而我的方法从一开始就有单独的变量,如果有很多这样的派生类(并且 A 仅用作基础)我认为我的是稍微优雅一点(您不必一遍又一遍地定义静态变量)。
      【解决方案3】:

      静态成员在应用程序中是唯一的。您的系统中有一个 A::a 常量。您可以做的是在B 中创建一个B::a 静态常量,它将隐藏A::a 静态(如果您不使用完全限定名称:

      class A {
      public:
         static const int a = 10;
      };
      static const int A::a;
      class B : public A {
      public:
         static const int a = 20;
         static void test();
      };
      static const int B::a;
      void B::test() {
         std::cout << a << std::endl;    // 20: B::a hides A::a
         std::cout << A::a << std::endl; // 10: fully qualified
      }
      

      【讨论】:

      • 是的,我知道。问题是当我有一个像 A *p = new B 这样的指针时。 p->test() 会打印 10 和 10。这就是我遇到的问题。似乎唯一的方法是使用虚拟方法。
      • @chmike:如果您需要多态性(基于实例的实际类型而不是指针/引用的不同行为),那么您确实需要虚拟方法。在我提供的示例中,A *p = new B; p-&gt;test() 甚至不会编译,因为test()A 级别不存在。
      • 是的,很明显。我错过了。所以答案是用虚方法替换静态变量a,并在派生类中重新定义方法。如果需要,该方法可以包含静态局部变量。如果你提供一个简单的代码示例,我会给你答案。
      • 这取决于变量代表什么,它可以是方法静态变量,也可以是从实际函数返回的静态类,这取决于更有意义的情况。
      【解决方案4】:

      你不能。所有派生类共享一个静态变量实例。

      【讨论】:

      • 是的,发布问题后才发现。在我发布问题并尝试删除问题后,您设法在 5 秒内回答。由于您的回复和 2 票赞成,删除问题被拒绝:)
      猜你喜欢
      • 1970-01-01
      • 2019-11-26
      • 1970-01-01
      • 2011-06-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多