我需要在一个 vector 中存储多种类型的模板类。
例如,对于:
template <typename T>
class templateClass{
bool someFunction();
};
我需要一个 vector 来存储所有:
templateClass<int> t1;
templateClass<char> t2;
templateClass<std::string> t3;
etc
据我所知这是不可能的,如果可以的话,有人能说一下吗?
如果不可能,有人可以解释如何进行以下工作吗?
作为一种变通方法,我尝试使用基础的非模板类并从中继承模板类。
class templateInterface{
virtual bool someFunction() = 0;
};
template <typename T>
class templateClass : public templateInterface{
bool someFunction();
};
然后我创建了一个 vector 来存储基本的“templateInterface”类:
std::vector<templateInterface> v;
templateClass<int> t;
v.push_back(t);
这产生了以下错误:
error: cannot allocate an object of abstract type 'templateInterface'
note: because the following virtual functions are pure within 'templateInterface'
note: virtual bool templateInterface::someFunction()
为了修复这个错误,我通过提供一个函数体使 templateInterface 中的函数不是纯虚函数,这是编译的,但是在调用函数时不使用覆盖,而是使用虚函数中的函数体。
例如:
class templateInterface{
virtual bool someFunction() {return true;}
};
template <typename T>
class templateClass : public templateInterface{
bool someFunction() {return false;}
};
std::vector<templateInterface> v;
templateClass<int> i;
v.push_back(i);
v[0].someFunction(); //This returns true, and does not use the code in the 'templateClass' function body
有没有办法解决这个问题,以便使用被覆盖的函数,或者是否有另一种解决方法可以将多个模板类型存储在一个 vector 中?
最佳答案
为什么您的代码不起作用:
在值上调用虚函数不使用多态性。它调用为编译器看到的这个确切符号的类型定义的函数,而不是运行时类型。当您将子类型插入基本类型的 vector 时,您的值将转换 为基本类型(“类型切片”),这不是您想要的。对它们调用函数现在将调用为基类型定义的函数,因为它不是该类型的is。
如何解决这个问题?
同样的问题可以用这个代码片段重现:
templateInterface x = templateClass<int>(); // Type slicing takes place!
x.someFunction(); // -> templateInterface::someFunction() is called!
多态性仅适用于 pointer 或 reference 类型。然后它将使用指针/引用后面的对象的运行时类型来决定调用哪个实现(通过使用它的vtable)。
就类型切片而言,转换指针是完全“安全的”。您的实际值根本不会被转换,多态性将按预期工作。
示例,类似于上面的代码片段:
templateInterface *x = new templateClass<int>(); // No type slicing takes place
x->someFunction(); // -> templateClass<int>::someFunction() is called!
delete x; // Don't forget to destroy your objects.
vector 呢?
因此,您必须在代码中采用这些更改。您可以简单地将 指针 存储到 vector 中的实际类型,而不是直接存储值。
使用指针时,您还必须注意删除分配的对象。为此,您可以使用自动删除的智能指针。 unique_ptr就是这样一种智能指针类型。只要指针超出范围(“唯一所有权” - 范围是所有者),它就会删除指针。假设您的对象的生命周期绑定(bind)到范围,这就是您应该使用的:
std::vector<std::unique_ptr<templateInterface>> v;
templateClass<int> *i = new templateClass<int>(); // create new object
v.push_back(std::unique_ptr<templateInterface>(i)); // put it in the vector
v.emplace_back(new templateClass<int>()); // "direct" alternative
然后,使用以下语法在其中一个元素上调用虚函数:
v[0]->someFunction();
确保您将所有应该可以被子类覆盖的函数虚拟。否则将不会调用其覆盖的版本。但是由于您已经引入了“接口(interface)”,我相信您正在使用抽象函数。
替代方法:
做你想做的事情的另一种方法是在 vector 中使用 variant 类型。有一些变体类型的实现,Boost.Variant是一个非常受欢迎的。如果您没有类型层次结构(例如,当您存储原始类型时),这种方法特别好。然后你会使用像 std::vector<boost::variant<int, char, bool>> 这样的 vector 类型。
关于C++ 一个包含多种类型模板类的 std::vector,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16527673/
使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta
我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何
我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>
为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
我正在使用puppet为ruby程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这
我可以得到Infinity和NaNn=9.0/0#=>Infinityn.class#=>Floatm=0/0.0#=>NaNm.class#=>Float但是当我想直接访问Infinity或NaN时:Infinity#=>uninitializedconstantInfinity(NameError)NaN#=>uninitializedconstantNaN(NameError)什么是Infinity和NaN?它们是对象、关键字还是其他东西? 最佳答案 您看到打印为Infinity和NaN的只是Float类的两个特殊实例的字符串
我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)
如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象
关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion为什么SecureRandom.uuid创建一个唯一的字符串?SecureRandom.uuid#=>"35cb4e30-54e1-49f9-b5ce-4134799eb2c0"SecureRandom.uuid方法创建的字符串从不重复?