C 11模板变量设计
|
我有很多抽象类字母的子类,如A,B,C,D等.字母有一个整数ID变量,并且Letter的每个子类都被赋予一个唯一的id.
然后我有另一个班,称之为Alphabet.字母表有一个 list<shared_ptr<Letter>> 会员.这是问题…我想优雅地将B和C或其他子类的Letter添加到字母的特定实例中.我认为最方便的方法是以某种方式使用子类的整数id.换句话说,我希望能够有像Alphabet.addLetter(int id)这样的东西,所以如果我做了alphabet1.add(14),它会以某种方式将H类的shared_ptr添加到列表中. 有没有一种优雅的方法来做到这一点,避免一些巨大的if语句,我需要不断更新每次添加或删除B,D,E等类之一?我希望有一些模板解决方案,但我不熟悉工厂和模板等高级c概念.我想要的天真的东西是某种矢量/地图,它将我的ID转换为类名,这样我就可以做类似的事情 list.push_back(shared_ptr<classVector(i)>(new classVector(i)) 或类似的东西,虽然我不知道这是否可能. 谢谢! 附:我刚刚选择了Alphabet示例,因为我不想给出不必要的细节.显然,我不是试图以这种愚蠢的方式设计字母表,哈哈. 编辑:我正在努力使这有意义.我的目标是能够以最小的努力快速创建Letter的新子类.我想避免输入看起来像……的代码 list.push_back(shared_ptr<X>(...)); 每次我写一封新信.这有意义吗? 解决方法
如果我正确地理解你,使用所谓的工厂模式,这相对容易.
如果您可以列出所有派生类型: 信头: struct Letter {
enum LetterEnum {LetterA,LetterB,LetterC,LetterCount};
virtual ~Letter() {} //base types should always have virtual destructor
virtual void foo() = 0;
static std::unique_ptr<Letter> construct(LetterEnum c);
};
实施标题: struct A : Letter {
void foo() override;
};
struct B : Letter {
void foo() override;
};
struct C : Letter {
void foo() override;
};
信体: std::unique_ptr<Letter> Letter::construct(Letter::LetterEnum c)
{
switch(c) {
case Letter::LetterA : return make_unique<A>();
case Letter::LetterB : return make_unique<B>();
case Letter::LetterC : return make_unique<C>();
default: throw ...;
}
}
用法: int main() {
char c;
std::cin >> c;
//get a letter of the derived type associated with the letter entered
std::unique_ptr<Letter> ptr = Letter::construct(c);
}
如果您无法列出所有派生类型: 允许派生类型使用Letter类注册自己,然后Letter可以使用它来创建每个派生类型.这样,添加和删除派生类型不会更改任何其他文件.简单! struct Letter {
virtual ~Letter() {} //destructor is always virtual when inheretence is involved
....
//this is a "shared" function in the Letter class itself
//it takes a letter,and returns a dynamically allocated instance
//of the derived type corresponding with that letter
static std::unique_ptr<Letter> construct(char c);
//this typedef represents the actual function that returns
//each dynamically allocated derived type
typedef std::function<std::unique_ptr<Letter>()> letter_ctor;
//this is a "shared" function in the Letter class itself
//it takes a letter,and a function that creates derived types,//and saves them inside the container ctors
static bool register(char c,letter_ctor func);
private:
//this is a "shared" member in the Letter class.
//There is only one shared by all of the Letters. Like a global.
//When you give it a letter,it gives you a function.
//and is VERY fast for large numbers of entries
static std::unordered_set<char,letter_ctor> ctors;
};
并在您的实现文件中: //here's the function that derived types register themselves with
//pretty straightforward,just inserts the pair into the unordered_map
bool Letter::register(char c,Letter::letter_ctor func)
{return Letter::ctors.insert(std::make_pair(c,std::move(func))).second;}
//and here's the function that creates the derived types
//it checks if the letter is in the unordered_map
//if the letter isn't there,it throws an exception
//otherwise,it calls the function associated with that letter
//which creates the derived type on the heap,and returns a pointer to it
std::unique_ptr<Letter> Letter::construct(char c)
{
auto it = Letter::ctors.find(c);
if (it == Letter::ctors.end())
throw ...;
return it->second(); //construct that letter
}
然后你的派生类型执行此操作: //you know this part
struct LetterA : public Letter
{
....
};
//derived types have to register themselves:
//this is a global,so when the program loads,it automatically calls this
//even before main runs*
//it registers the letter 'A' and a function that creates a LetterA class on the heap
static bool registerA = Letter::register('A',[](){return make_unique<LetterA>();});
然后你可以轻松创建arbirary派生类型! int main() {
char c;
std::cin >> c;
//get a letter of the derived type associated with the letter entered
std::unique_ptr<Letter> ptr = Letter::construct(c);
}
*它并不总是在main之前被调用.如果你有问题,请加一个bool init_A();在A头文件中,并在A实现文件中bool init_A(){return true;},并在主文件中有静态bool AInit = init_A();应该强迫它.但这在实践中几乎从不需要. 作为旁注,这些取决于有一个make_unique,它应该在C 11中,但由于疏忽而被遗漏.它将在C 14中.与此同时,使用: template<class T,class...Us>
std::unique_ptr<T> make_unique(Us&&...us)
{return std::unique_ptr<T>(new T(std::forward<Us>(us)...));}
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
