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)...));} (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |