c++ - C++ 泛型和多态:这种模式可行吗?
问题描述
我了解多态性和泛型如何在其他编程语言(Java、C#、Typescript 等)中交互。然而,在 C++ 中,它感觉就像我想使用的模式失败了。
在这个例子中,我想要一个Name
扩展Word
s 的 s 列表。我想将我的名字列表传递给一个接受单词列表的方法,但我不能。我可以用我的名字填充单词列表,但这会丢失类型信息,这意味着我不能调用任何继承到 Name 类的方法。
#include <iostream>
#include <string>
#include <list>
class Word{
public:
virtual void say() = 0;
};
class Name : public Word{
std::string name;
public:
Name(std::string name){
this-> name = name;
}
void say() override{
std::cout << name << std::endl;
}
void important_name_function(){
// Something very important I want to call
}
};
void say_one(Word* w){
w-> say();
}
void say_all(std::list<Word*> list){
for(Word* w: list){
w-> say();
}
}
int main(){
std::list<Word*> words = {new Name("Kai"), new Name("Ben"), new Name("Sam")};
say_one(words.front()); //Works, due to the magic of polymorphism
say_all(words); //Works, due to the magic of polymorphism
std::list<Name*> names = {new Name("Kai"), new Name("Ben"), new Name("Sam")};
say_one(names.front()); //STILL works due to the magic of polymorphism AND type information is retained
say_all(names); //Fails but feels like it shouldn't
}
例如,在 Java 中,我可以通过将 say all 定义为
static <T extends Word> void say_all (java.util.LinkedList<T> list){
for(T w:list){
w.say();
}
}
但是,在 C++ 中寻找这个解决方案在我看来是一个丑陋的解决方案(C++ 相当于使用 <T extends Class> 作为 java 参数/返回类型)
对我来说,这意味着以下其中一项是正确的:
- 这种模式本质上是不可取的,不应该追求。
- 我认为丑陋的解决方案实际上是最好的解决方案和/或
- 我错误地将其访问为丑陋有另一种创建此模式的解决方案
解决方案
- 我错误地将其评估为丑陋
那。
我不觉得以下丑陋:
template<class T>
void say_all(const std::list<T*>& list) {
for (T* w : list) {
w->say();
}
}
请注意,您根本不必T
在示例中进行限制。在Java中无法真正匹配。
仅当您实际上需要限制T
为以下实例时Word
:
template<class T, typename = std::enable_if_t<std::is_base_of<Word, T>::value>>
void say_all(const std::list<T*>& list) {
for (T* w : list) {
w->say();
}
}
或与概念:
template<typename T>
concept IsWord = std::is_base_of<Word, T>::value;
template<class T> requires IsWord<T>
void say_all(const std::list<T*>& list) {
for(T* w : list) {
w->say();
}
}
旁注:
- 通过引用传递对象来避免不必要地复制对象。
- 为了减少内存泄漏,请避免使用运算符
new
并使用std::list<std::unique_ptr<Word>>
andstd::make_unique
来代替。
推荐阅读
- node.js - 错误 [ERR_HTTP_HEADERS_SENT] 未能上传图片
- python - 按字典值过滤 Pandas 系列
- java - Apache Storm - KafkaSpout 不使用来自 Kafka 主题的消息
- sql - 知道下面的 SQL 代码在做什么
- math - 如何将操作的输出保持在 2 个设定值之间?(极限,模数)
- oracle - 双引号分隔标识符错误 SQL
- python-3.x - 类不运行方法(简单) 我如何运行它?
- javascript - SecurityError:React 上带有 window.open 弹出窗口的“跨域对象”
- xml - IIS 服务 XML 和“接受但忽略”POST
- mongodb - 带有 MongoDB findOne 方法的打字稿不适用于泛型