C++ 从静态类继承

C++ 从静态类继承,c++,std,C++,Std,我有一系列静态类,用于填充和访问std::map中的数据 由于它们是静态的,所以很容易将其设置为仅在需要时填充地图,并且只需要填充一次 大致如下: class MyClass { public: string at(int key) { PopulateEmptyMap(); return myMap.at(key); } private: void PopulateEmptyMap() { if(!myMap.empty()) retu

我有一系列静态类,用于填充和访问std::map中的数据

由于它们是静态的,所以很容易将其设置为仅在需要时填充地图,并且只需要填充一次

大致如下:

class MyClass
{
public:
  string at(int key)
  {
    PopulateEmptyMap();
    return myMap.at(key);
  }

private:
  void PopulateEmptyMap()
  {
    if(!myMap.empty())
      return;
    PopulateMap();
  }

  void PopulateMap()
  {
    myMap[1] = "str1";
    myMap[2] = "str2";
  }

  static map<int, string> myMap;
};
class-MyClass
{
公众:
字符串位于(int键)
{
PopulateEmptyMap();
返回myMap.at(键);
}
私人:
void PopulateEmptyMap()
{
如果(!myMap.empty())
返回;
PopulateMap();
}
void PopulateMap()
{
myMap[1]=“str1”;
myMap[2]=“str2”;
}
静态地图myMap;
};
实际的类更复杂,有多个贴图,但您可以理解

我有一系列类似这样的类,除了映射的类型和值之外,它们实际上是相同的

我希望代码存在于一个地方,而不是让多个类都复制相同的代码,但我不知道如何做到这一点

我的第一个想法是从一个拥有所有共享代码的模板类继承。函数PopulateMap将变成纯虚拟的,然后由每个继承类实现。当然,这不起作用,因为函数不可能同时是静态和虚拟的


对于我正在尝试的事情,我有什么选择?

没有静态类。您描述的是一个只有静态数据的类,这些静态数据只填充一次,然后再使用。您可以拥有任意数量的非静态函数(包括虚拟函数和常规函数),只要它们只处理静态成员数据

这是你想要的东西

#include <iostream>
#include <string>
#include <map>

// A base class template that has a virtual function
// to allow derived classes to fill up the map.
template <typename Key, typename Value>
class MyTemplateClass
{
   public:

      Value at(Key const& key)
      {
         PopulateEmptyMap();
         return myMap.at(key);
      }

      void PopulateEmptyMap()
      {
         if(!myMap.empty())
            return;
         PopulateMap();
      }

   protected:

      virtual void PopulateMap() = 0;

      static std::map<Key, Value> myMap;
};

// Define the static member data of the class template.
template <typename Key, typename Value>
std::map<Key, Value> MyTemplateClass<Key, Value>::myMap;

// Define a sub-calss of MyTemplateClass that works
// int as key and string as value.
class MyClass1 : public MyTemplateClass<int, std::string>
{
   protected:

      virtual void PopulateMap()
      {
         myMap[1] = "str1";
         myMap[2] = "str2";
      }
};

// Define a sub-calss of MyTemplateClass that works
// int as key and int as value.
class MyClass2 : public MyTemplateClass<int, int>
{
   protected:

      virtual void PopulateMap()
      {
         myMap[1] = 10;
         myMap[2] = 20;
      }
};

int main()
{
   MyClass1 c1;
   std::cout << c1.at(1) << std::endl;
   std::cout << c1.at(2) << std::endl;

   MyClass2 c2;
   std::cout << c2.at(1) << std::endl;
   std::cout << c2.at(2) << std::endl;
}
但是,您可以使用第三个参数
MyTemplateClass
来解决这个问题

#include <iostream>
#include <string>
#include <map>

template <typename Key, typename Value, typename Derived>
class MyTemplateClass
{
   public:

      Value at(Key const& key)
      {
         PopulateEmptyMap();
         return myMap.at(key);
      }

      void PopulateEmptyMap()
      {
         if(!myMap.empty())
            return;
         PopulateMap();
      }

   protected:

      virtual void PopulateMap() = 0;

      static std::map<Key, Value> myMap;
};


template <typename Key, typename Value, typename Derived>
std::map<Key, Value> MyTemplateClass<Key, Value, Derived>::myMap;

class MyClass1 : public MyTemplateClass<int, std::string, MyClass1>
{
   protected:

      virtual void PopulateMap()
      {
         myMap[1] = "str1";
         myMap[2] = "str2";
      }
};

class MyClass2 : public MyTemplateClass<int, int, MyClass2>
{
   protected:

      virtual void PopulateMap()
      {
         myMap[1] = 10;
         myMap[2] = 20;
      }
};

class MyClass3 : public MyTemplateClass<int, int, MyClass3>
{
   protected:

      virtual void PopulateMap()
      {
         myMap[1] = 30;
         myMap[2] = 40;
      }
};

int main()
{
   MyClass1 c1;
   std::cout << c1.at(1) << std::endl;
   std::cout << c1.at(2) << std::endl;

   MyClass2 c2;
   std::cout << c2.at(1) << std::endl;
   std::cout << c2.at(2) << std::endl;

   MyClass3 c3;
   std::cout << c3.at(1) << std::endl;
   std::cout << c3.at(2) << std::endl;
}
单态模式 另一种可能适合您的方法是使用

#包括
#包括
#包括
模板
类MyTemplateClass
{
公众:
值(键常量和键)
{
PopulateEmptyMap();
返回myMap.at(键);
}
void PopulateEmptyMap()
{
如果(!myMap.empty())
返回;
PopulateMap();
}
受保护的:
虚拟void PopulateMap()=0;
静态std::map myMap;
};
模板
std::map MyTemplateClass::myMap;
类MyClass1:公共MyTemplateClass
{
公众:
静态MyClass1*实例()
{
静态MyClass1状态;
返回&实例;
}
void PopulateMap()
{
myMap[1]=“str1”;
myMap[2]=“str2”;
}
私人:
//不允许客户端创建对象
MyClass1(){}
~MyClass1(){}
};
int main()
{
//使用instance()接口访问数据。

St::CUT在(1)C++中没有静态类。因此,使用这个类,没有办法用一个命令访问数据:<代码> MyClass::AT(2)< /Cord>,而您需要始终使用两个命令:<代码> MyClass myClass;MyCal.At(2)。;
也许我不应该给类一个静态成员,而是应该有一个工厂方法,返回一个静态的、完全填充的类。
#include <iostream>
#include <string>
#include <map>

template <typename Key, typename Value, typename Derived>
class MyTemplateClass
{
   public:

      Value at(Key const& key)
      {
         PopulateEmptyMap();
         return myMap.at(key);
      }

      void PopulateEmptyMap()
      {
         if(!myMap.empty())
            return;
         PopulateMap();
      }

   protected:

      virtual void PopulateMap() = 0;

      static std::map<Key, Value> myMap;
};


template <typename Key, typename Value, typename Derived>
std::map<Key, Value> MyTemplateClass<Key, Value, Derived>::myMap;

class MyClass1 : public MyTemplateClass<int, std::string, MyClass1>
{
   protected:

      virtual void PopulateMap()
      {
         myMap[1] = "str1";
         myMap[2] = "str2";
      }
};

class MyClass2 : public MyTemplateClass<int, int, MyClass2>
{
   protected:

      virtual void PopulateMap()
      {
         myMap[1] = 10;
         myMap[2] = 20;
      }
};

class MyClass3 : public MyTemplateClass<int, int, MyClass3>
{
   protected:

      virtual void PopulateMap()
      {
         myMap[1] = 30;
         myMap[2] = 40;
      }
};

int main()
{
   MyClass1 c1;
   std::cout << c1.at(1) << std::endl;
   std::cout << c1.at(2) << std::endl;

   MyClass2 c2;
   std::cout << c2.at(1) << std::endl;
   std::cout << c2.at(2) << std::endl;

   MyClass3 c3;
   std::cout << c3.at(1) << std::endl;
   std::cout << c3.at(2) << std::endl;
}
#include <iostream>
#include <string>
#include <map>

template <typename Key, typename Value, typename Derived>
class MyTemplateClass
{
   public:

      static Value at(Key const& key)
      {
         PopulateEmptyMap();
         return myMap.at(key);
      }

      static void PopulateEmptyMap()
      {
         if(!myMap.empty())
            return;
         Derived::PopulateMap();
      }

   protected:

      static std::map<Key, Value> myMap;
};


template <typename Key, typename Value, typename Derived>
std::map<Key, Value> MyTemplateClass<Key, Value, Derived>::myMap;

class MyClass1 : public MyTemplateClass<int, std::string, MyClass1>
{
   public:

      static void PopulateMap()
      {
         myMap[1] = "str1";
         myMap[2] = "str2";
      }
};

int main()
{
   // Access the data without needing to create an object.
   std::cout << MyClass1::at(1) << std::endl;
   std::cout << MyClass1::at(2) << std::endl;

   // They are also accessible using an object.
   MyClass1 c1;
   std::cout << c1.at(1) << std::endl;
   std::cout << c1.at(2) << std::endl;
}
#include <iostream>
#include <string>
#include <map>

template <typename Key, typename Value, typename Derived>
class MyTemplateClass
{
   public:

      Value at(Key const& key)
      {
         PopulateEmptyMap();
         return myMap.at(key);
      }

      void PopulateEmptyMap()
      {
         if(!myMap.empty())
            return;
         PopulateMap();
      }

   protected:

      virtual void PopulateMap() = 0;

      static std::map<Key, Value> myMap;
};


template <typename Key, typename Value, typename Derived>
std::map<Key, Value> MyTemplateClass<Key, Value, Derived>::myMap;

class MyClass1 : public MyTemplateClass<int, std::string, MyClass1>
{
   public:

      static MyClass1* instance()
      {
         static MyClass1 theInstance;
         return &theInstance;
      }

      void PopulateMap()
      {
         myMap[1] = "str1";
         myMap[2] = "str2";
      }

   private:

      // Disallow creation of objects by clients
      MyClass1() {}
      ~MyClass1() {}
};

int main()
{
   // Access the data using the instance() interface.
   std::cout << MyClass1::instance()->at(1) << std::endl;
   std::cout << MyClass1::instance()->at(2) << std::endl;
}