Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.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++中,向量类存储对象数组。在本例中,我存储指向派生类对象(Dogs)的指针。在某种程度上,我想把这个向量当作指向基类对象(动物)的指针。这是“正确的”/无争议的方式,对吗?为什么我不能这样做 #include <vector> using namespace std; class Animal { }; class Dog : public Animal { }; int main(int argc, char *argv[]) { vector<Dog*> dogs; dogs.push_back(new Dog()); dogs.push_back(new Dog()); vector<Animal*> animals = dogs; // This doesn't seem to work. // This is really what I want to do... vector<Animal*> all_animals[] = {dogs, cats, birds}; } #包括 使用名称空间std; 动物类{}; 犬类:公共动物{}; int main(int argc,char*argv[]){ 病媒狗; 狗。推回(新狗); 狗。推回(新狗); 向量动物=狗;//这似乎不起作用。 //这真的是我想做的。。。 传播所有动物[]={狗、猫、鸟}; }_C++_Inheritance - Fatal编程技术网

我想要一个派生类指针的向量作为基类指针 C++中,向量类存储对象数组。在本例中,我存储指向派生类对象(Dogs)的指针。在某种程度上,我想把这个向量当作指向基类对象(动物)的指针。这是“正确的”/无争议的方式,对吗?为什么我不能这样做 #include <vector> using namespace std; class Animal { }; class Dog : public Animal { }; int main(int argc, char *argv[]) { vector<Dog*> dogs; dogs.push_back(new Dog()); dogs.push_back(new Dog()); vector<Animal*> animals = dogs; // This doesn't seem to work. // This is really what I want to do... vector<Animal*> all_animals[] = {dogs, cats, birds}; } #包括 使用名称空间std; 动物类{}; 犬类:公共动物{}; int main(int argc,char*argv[]){ 病媒狗; 狗。推回(新狗); 狗。推回(新狗); 向量动物=狗;//这似乎不起作用。 //这真的是我想做的。。。 传播所有动物[]={狗、猫、鸟}; }

我想要一个派生类指针的向量作为基类指针 C++中,向量类存储对象数组。在本例中,我存储指向派生类对象(Dogs)的指针。在某种程度上,我想把这个向量当作指向基类对象(动物)的指针。这是“正确的”/无争议的方式,对吗?为什么我不能这样做 #include <vector> using namespace std; class Animal { }; class Dog : public Animal { }; int main(int argc, char *argv[]) { vector<Dog*> dogs; dogs.push_back(new Dog()); dogs.push_back(new Dog()); vector<Animal*> animals = dogs; // This doesn't seem to work. // This is really what I want to do... vector<Animal*> all_animals[] = {dogs, cats, birds}; } #包括 使用名称空间std; 动物类{}; 犬类:公共动物{}; int main(int argc,char*argv[]){ 病媒狗; 狗。推回(新狗); 狗。推回(新狗); 向量动物=狗;//这似乎不起作用。 //这真的是我想做的。。。 传播所有动物[]={狗、猫、鸟}; },c++,inheritance,C++,Inheritance,错误: Untitled.cpp:11:18: error: no viable conversion from 'vector<class Dog *>' to 'vector<class Animal *>' vector<Animal*> animals = dogs; ^ ~~~~ /usr/include/c++/4.2.1/bits/stl_vector.h:231:7: note:

错误:

Untitled.cpp:11:18: error: no viable conversion from 'vector<class Dog *>' to 'vector<class Animal *>'
    vector<Animal*> animals = dogs;
                    ^         ~~~~
/usr/include/c++/4.2.1/bits/stl_vector.h:231:7: note: candidate constructor not viable: no known conversion from 'vector<Dog *>' to 'const std::vector<Animal *, std::allocator<Animal *> > &' for 1st argument
  vector(const vector& __x)
  ^
Untitled.cpp:11:18:错误:从“vector”到“vector”没有可行的转换
媒介动物=狗;
^         ~~~~
/usr/include/c++/4.2.1/bits/stl_vector.h:231:7:注意:候选构造函数不可行:第一个参数没有从“vector”到“const std::vector&”的已知转换
向量(常数向量和x)
^

std::vector有一个复制构造函数,但它要求您复制完全相同类型的向量。幸运的是,还有另一个构造函数,它接受一对迭代器并添加范围内的所有元素,因此您可以这样做:

vector<Animal*> animals(dogs.begin(),dogs.end());

您可以将您的狗向量创建为:

vector<Animal*> dogs;

稍后,在访问时返回,您可以毫无问题地完成真正想做的事情!也就是说,只需做:

class Animal {
   public:
      std::string GetNoise() const = 0;
};
class Dog : public Animal {
   public:
      std::string GetNoise() const { return "Bark!"; }
};
class Cat : public Animal {
   public:
      std::string GetNoise() const { return "Meow"; }
      bool        LikesSleeping() const { return true; }
};

Dog* d = new Dog;
Cat* c = new Cat;
vector<Animal*> all_animals;
all_animals.push_back(d, c);

// then, later...

// this will print "Bark!"
std::cout << all_animals[0]->GetNoise() std::endl;

// if you know the type somehow
Cat* x = dynamic_cast<Cat*>(all_animals[1]);
const bool y = x->LikesSleeping();

dogs的向量
是否从动物的向量中插入?显然不是!但是所做的只是将类的名称从
std::vector
更改为
vectorOfDogs
接受的解决方案很好,但有一个很大的缺点:它保留了相关向量内容的副本。任何时候更新一个向量,我们都需要更新冗余数据以保持全局状态一致。由于不太喜欢,决定尝试回避这个问题(不幸的是,需要发现这需要做很多工作……):

类动物
{
结构包装器
{
虚拟~Wrapper(){}
虚拟动物*begin()=0;
虚拟动物*end()=0;
};
模板
结构特定包装器:包装器
{
T&动物;
特殊包装(T和动物)
:动物
{ }
动物*begin()覆盖
{
return*animals.begin();
}
动物*end()覆盖
{
return*animals.end();
}
};
std::向量包装器;
公众:
类迭代器:public std::iterator
{
朋友级动物;
decltype(包装器):迭代器当前,结束;
动物*动物;
迭代器(decltype(当前)开始,decltype(结束)结束)
:当前(开始)、结束(结束)/、动物(空PTR)
{
while(current!=end&&(*current)->begin()==(*current)->end())
{
++电流;
}
动物=当前==结束?空ptr:(*当前)->开始();
}
公众:
布尔运算符==(迭代器常量和其他)
{
返回current==other.current&&animal==other.animal;
}
布尔运算符!=(迭代器常量和其他)
{
返回!(*此==其他);
}
迭代器和运算符++()
{
如果(++动物==(*当前)->end())
{
++电流;
动物=当前==结束?空ptr:(*当前)->开始();
}
归还*这个;
}
迭代器运算符++(int)
{
迭代器i(*this);
++*这,;
返回i;
}
动物*操作员*()
{
返回动物;
}
动物*操作员->()
{
返回动物;
}
};
迭代器begin()
{
返回迭代器(wrappers.begin(),wrappers.end());
}
迭代器结束()
{
返回迭代器(wrappers.end(),wrappers.end());
}
模板
无效推回(标准::矢量和v)
{
包装物。将包装物放回原位(新的特殊包装物(v));
}
};

到目前为止,我只实现了一个前向迭代器,其中一个可以提供更多的操作符来进行双向甚至随机访问。此外,我们可能会添加常量迭代器,(常量)反向迭代器,…

@Mahesh,因为你永远都不想做
无效oops(向量和动物){动物。推回(新猫)}向量狗;oops(狗)
。不过,这种解决方案有一个缺点:
所有动物
维护其他载体内容的副本,因此如果更新其中一个,所有动物都不会自动更新…@molbdnilo这是什么样的参数?它与
void oops(动物和动物){Animal=*新猫;}狗*狗有什么不同;oops(*狗)
dogs.push_back((Animal*)new Dog());
class Animal {
   public:
      std::string GetNoise() const = 0;
};
class Dog : public Animal {
   public:
      std::string GetNoise() const { return "Bark!"; }
};
class Cat : public Animal {
   public:
      std::string GetNoise() const { return "Meow"; }
      bool        LikesSleeping() const { return true; }
};

Dog* d = new Dog;
Cat* c = new Cat;
vector<Animal*> all_animals;
all_animals.push_back(d, c);

// then, later...

// this will print "Bark!"
std::cout << all_animals[0]->GetNoise() std::endl;

// if you know the type somehow
Cat* x = dynamic_cast<Cat*>(all_animals[1]);
const bool y = x->LikesSleeping();
class vectorOfDogs {
    Dog* myDogs;
    //...
}

class vectorOfAnimals {
    Animal* myAnimals;
    //...
}
class AllAnimals
{
    struct Wrapper
    {
        virtual ~Wrapper() { }
        virtual Animal* begin() = 0;
        virtual Animal* end() = 0;
    };

    template <typename T>
    struct SpecificWrapper : Wrapper
    {
        T& animals;
        SpecificWrapper(T& animals)
                : animals(animals)
        { }
        Animal* begin() override
        {
            return *animals.begin();
        }
        Animal* end() override
        {
            return *animals.end();
        }
    };

    std::vector<std::unique_ptr<Wrapper>> wrappers;

public:
    class iterator : public std::iterator<std::forward_iterator_tag, Animal*>
    {
        friend class AllAnimals;
        decltype(wrappers)::iterator current, end;
        Animal* animal;
        iterator(decltype(current) begin, decltype(end) end)
                : current(begin), end(end)//, animal(nullptr)
        {
            while(current != end && (*current)->begin() == (*current)->end())
            {
                ++current;
            }
            animal = current == end ? nullptr : (*current)->begin();
        }
    public:
        bool operator==(iterator const& other)
        {
            return current == other.current && animal == other.animal;
        }
        bool operator!=(iterator const& other)
        {
            return !(*this == other);
        }
        iterator& operator++()
        {
            if(++animal == (*current)->end())
            {
                ++current;
                animal = current == end ? nullptr : (*current)->begin();
            }
            return *this;
        }
        iterator operator++(int)
        {
            iterator i(*this);
            ++*this;
            return i;
        }
        Animal* operator*()
        {
            return animal;
        }
        Animal* operator->()
        {
            return animal;
        }
    };

    iterator begin()
    {
        return iterator(wrappers.begin(), wrappers.end());
    }
    iterator end()
    {
        return iterator(wrappers.end(), wrappers.end());
    }

    template <typename T>
    void push_back(std::vector<T*>& v)
    {
        wrappers.emplace_back(new SpecificWrapper<decltype(v)>(v));
    }
};