gpt4 book ai didi

c++ - 从静态类继承

转载 作者:行者123 更新时间:2023-11-30 04:05:34 26 4
gpt4 key购买 nike

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

由于它们是静态的,因此很容易进行设置,以便仅在需要时填充 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)更复杂,有多个 map ,但你明白了。

我有一系列这样的类,除了 map 的类型和值之外,它们几乎完全相同。

我不想让多个类都重现相同的代码,而是希望代码存在于一个地方,但我不知道该怎么做。

我的第一个想法是继承一个具有所有共享代码的模板类。 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 的派生类使用 int作为键和 int作为值(value),你会看到意想不到的行为。 MyTemplateClass<int, int> 只能有一个实例化.

// This will lead to unexpected behavior. You will get either 10 and 20 in
// the map or 30 and 40. You will not get all four in the map.
// If the behavior of MyClass2 seems sane, the behavior of MyClass3 will seem
// the opposite, or vice versa.
class MyClass3 : public MyTemplateClass<int, int>
{
protected:

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

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

这对我有用。希望它对你有用。

更新

有几个选项可供您选择,不需要在堆栈上创建对象。

全部static成员

您可以设计类以通过 static 访问所有内容成员函数。

#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;
}

单例模式

另一种可能对您有用的方法是使用 singleton pattern .

#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;
}

关于c++ - 从静态类继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23235715/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com