C++ 从静态类继承
我有一系列静态类,用于填充和访问std::map中的数据 由于它们是静态的,所以很容易将其设置为仅在需要时填充地图,并且只需要填充一次 大致如下: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
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;
}