Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 我可以播放std::vector<;动物*>;到std::vector<;狗*>;不看每个元素?_C++_Templates_Vector_Casting - Fatal编程技术网

C++ 我可以播放std::vector<;动物*>;到std::vector<;狗*>;不看每个元素?

C++ 我可以播放std::vector<;动物*>;到std::vector<;狗*>;不看每个元素?,c++,templates,vector,casting,C++,Templates,Vector,Casting,我有一个基类,有几个类扩展它。我有一些通用的库实用程序,它创建一个向量,其中包含指向基类的指针,这样任何子类都可以工作。如何将向量的所有元素强制转换为特定的子类 // A method is called that assumes that a vector containing // Dogs casted to Animal is passed. void myDogCallback(vector<Animal*> &animals) { // I want to

我有一个基类,有几个类扩展它。我有一些通用的库实用程序,它创建一个向量,其中包含指向基类的指针,这样任何子类都可以工作。如何将向量的所有元素强制转换为特定的子类

// A method is called that assumes that a vector containing
// Dogs casted to Animal is passed.
void myDogCallback(vector<Animal*> &animals) {
    // I want to cast all of the elements of animals to
    // be dogs.
    vector<Dog*> dogs = castAsDogs(animals);
}
//调用一个方法,该方法假定包含
//被铸造成动物的狗被传了。
无效myDogCallback(病媒和动物){
//我想把动物的所有元素都投射到
//做狗。
病媒狗=卡斯塔斯狗(动物);
}
我的天真解决方案如下所示:

// A method is called that assumes that a vector containing
// Dogs casted to Animal is passed.
void myDogCallback(vector<Animal*> &animals) {
    // I want to cast all of the elements of animals to
    // be dogs.
    vector<Dog*> dogs;
    vector<Animal*>::iterator iter;
    for ( iter = animals.begin(); iter != animals.end(); ++iter ) {
        dogs.push_back(dynamic_cast<Dog*>(*iter));
    }
}
//调用一个方法,该方法假定包含
//被铸造成动物的狗被传了。
无效myDogCallback(病媒和动物){
//我想把动物的所有元素都投射到
//做狗。
病媒狗;
向量:迭代器iter;
for(iter=animals.begin();iter!=animals.end();++iter){
狗。推回(动态投射(*iter));
}
}

当动物向量包含其他动物特化时,您编写的代码将向dogs向量中放入一堆空指针

vector<Dog*> dogs;
vector<Animal*>::iterator iter;
Dog* dog;

for( iter = animals.begin(); iter != animals.end(); ++iter )
{
  dog = dynamic_cast<Dog*>(*iter);
  if( dog )
  {
    dogs.push_back( dog );
  }
}
矢量狗;
向量:迭代器iter;
狗*狗;
for(iter=animals.begin();iter!=animals.end();++iter)
{
dog=动态熔铸(*iter);
如果(狗)
{
狗。推回(狗);
}
}

通常,使用动态投影进行向下投影不是很好。您可能应该重构代码,这样就不需要使用显式向下转换

有关更多信息,请参阅


UPD另请参见(搜索“为什么我不能将向量指定给向量?”)

您可以使用
std::transform
。它仍然在内部使用
for()
,但您将得到两个字符串实现:

#include <vector>
#include <algorithm>
using namespace std;

struct Animal { virtual ~Animal() {} };
struct Dog : Animal { virtual ~Dog() {} };

template<typename Target>
struct Animal2Target { Target* operator ()( Animal* value ) const { return dynamic_cast<Target*>(value); } };

void myDogCallback(vector<Animal*> &animals) {
{
    vector<Dog*> dogs;
    transform( animals.begin(), animals.end(), dogs.begin(), Animal2Target<Dog>() );
}
#包括
#包括
使用名称空间std;
结构动物{virtual~Animal(){};
结构狗:动物{virtual~Dog(){};
模板
struct Animal2Target{Target*操作符()(动物*值)const{return dynamic_cast(值);};
无效myDogCallback(病媒和动物){
{
病媒狗;
转换(animals.begin()、animals.end()、dogs.begin()、Animal2Target());

}
有两种选择。最简单的方法是在
的情况下使用
remove\u copy\u之类的方法。我无法解释为什么他们会这样称呼它,但它会将不满足谓词的元素从一个容器复制到另一个容器。以下是基本思想(未测试):


这很粗糙,但我希望它能向你展示基本原理。

如果你说你能保证每个元素都是真正的狗,那么只需
静态施法即可

void myDogCallback(vector<Animal*> &animals) {

    const vector<Animal*>::size_type numAnimals = animals.size();

    vector<Dog*> dogs;
    dogs.reserve( numAnimals );

    for ( vector<Animal*>::size_type i = 0; i < numAnimals; ++i ) {
        dogs.push_back(static_cast<Dog*>( animals[i] ));
    }
}
void myDogCallback(向量和动物){
常量向量::size_type numAnimals=anives.size();
病媒狗;
狗。保护区(纽曼马尔);
对于(向量::大小\类型i=0;i
我通常会从人们那里得到下意识的反应,这是不好的,你应该总是使用
dynamic\u cast
,但是,实际上,如果你能对类型做出保证,那么它是完全安全的,我认为这是一件明智的事


此外,您的保证意味着新向量具有相同的大小,因此保留相同的空间,以避免在每个
推回
中进行任何分配。作为替代循环,我使用了索引,只是因为我始终认为使用索引进行迭代必须比迭代器更快,但这可能是胡说八道:)

如果您可以保证,如果你的
std::vector
只包含
Dog*
,你可以使用
reinterpret\u cast

std::transform
方法与
static\u cast
混合使用(因为你确信它的安全性),可以如下所示:

std::transform(animals.begin(), animals.end(),
               std::back_insert_iterator<std::vector<Dog*>>(dogs),
               [](auto ptr) { return static_cast<Dog*>(ptr); });
std::transform(anists.begin(),anists.end(), 标准::返回插入迭代器(狗), [](自动ptr){return static_cast(ptr);};
复制:这不是完全重复-注意,他不是从
向量
复制到
向量
,而是从另一个角度复制!我猜他在寻找一种自动/隐含的沮丧!感谢反馈。:)不确定如何问这个问题,是的,很难知道要搜索什么!这仍然是“查看每个元素”,则流的排列方式不同。违反严格的别名:
void myDogCallback(vector<Animal*> &animals) {

    const vector<Animal*>::size_type numAnimals = animals.size();

    vector<Dog*> dogs;
    dogs.reserve( numAnimals );

    for ( vector<Animal*>::size_type i = 0; i < numAnimals; ++i ) {
        dogs.push_back(static_cast<Dog*>( animals[i] ));
    }
}
std::transform(animals.begin(), animals.end(),
               std::back_insert_iterator<std::vector<Dog*>>(dogs),
               [](auto ptr) { return static_cast<Dog*>(ptr); });