通过 <vector> 删除复制构造函数等,按值(无指针)将具有相同基类的对象存储在C++中
Store objects with the same base class in C++ <vector> by value (no pointers) by deleting the copy constructor etc
我读到(这里https://stackoverflow.com/a/18351550/1474291),这是可能的,在<vector>
继承相同的基类的派生类的存储对象。为了防止对象切片,我需要删除移动构造函数,复制构造函数和复制赋值。
注意:我感兴趣的是按值存储对象,而不是按指针存储。
我试图用Visual c++ 2013和MinGW (GCC 4.8.2和4.9.1)编译以下代码,但代码无法编译。我想在c++ 11中通过使用"delete", "default"和旧的方法来做到这一点。
正确的实现方法是什么?(实际上c++编译器支持"delete"answers"default"吗?)
下面是我的示例代码:#include <iostream>
#include <vector>
using namespace std;
#if __cplusplus > 199711L
#define CPP11
#endif
class Animal {
public:
Animal() {
cout << "Making animal:";
}
virtual ~Animal() {
cout << "Send the animal home!";
}
#ifdef CPP11
public:
Animal(Animal&&) = delete;
Animal(Animal const&) = delete;
Animal& operator=(Animal&) = delete;
#else // C++98
private:
Animal(Animal const&);
Animal& operator=(Animal&);
#endif // CPP11
public:
virtual void speak() {
cout << "I am an animal!";
}
};
class Dog : public Animal {
public:
Dog() {
cout << "Making dog:";
}
virtual ~Dog() {
cout << "Send the dog home!";
}
#ifdef CPP11
public:
Dog(Dog&&) = default;
Dog(Dog const&) = default;
Dog& operator=(Dog&) = default;
#else // C++98
private:
Dog(Dog const&);
Dog& operator=(Dog&);
#endif // CPP11
virtual void speak() {
cout << "I am a dog!";
}
};
class Cat : public Animal{
public:
Cat() {
cout << "Making cat";
}
virtual ~Cat() {
cout << "Sending the cat home!";
}
#ifdef CPP11
public:
Cat(Cat&&) = default;
Cat(Cat const&) = default;
Cat& operator=(Cat&) = default;
#else // C++98
private:
Cat(Cat const&);
Cat& operator=(Cat&);
#endif // CPP11
virtual void speak() {
cout << "I am a cag!";
}
};
int main()
{
vector<Animal> animals;
for (int i = 0; 10 > i; i++) {
Dog dog;
animals.push_back(dog);
Cat cat;
animals.push_back(cat);
}
#ifdef CPP11
for (Animal& animal: animals) {
animal.speak();
}
#else
for (std::vector<Animal>::iterator currentAnimal = animals.begin();
currentAnimal != animals.end();
++currentAnimal) {
currentAnimal->speak();
}
#endif // CPP11
return 0;
}
我认为您忽略的一点是容器需要为它包含的每个元素留出特定数量的内存。所以容器的元素固定大小
现在你想把不同大小的对象塞进这些固定大小的盒子里。你知道这是怎么回事吗?
当你试图将一个比基类大的派生对象塞进一个用来保存基类大小的对象的变量(读取容器元素)时,你将得到切片。
当将派生类型的对象放入基类向量中时,无法避免对象切片。你提到的问题解释了如何通过不可能复制相关类型的对象来避免对象切片。这意味着你得到的不是对象切片,而是编译错误。
除此之外,实现可以按值存储的"多态"类型的一种可能方法是实现一个单一类型,其实现可以在运行时设置。下面的内容:class Animal
{
public:
void talk() const { impl_->talk(); }
// implement copy, assignment, move copy, move assignment
// implement constructor allowing to specify the implementation
private:
std::unique_ptr<AnimalImpl> impl_;
};
struct AnimalImpl
{
virtual void talk() const = 0;
virtual ~AninalImpl() {}
};
struct Elephant : AnimalImpl
{
void talk() const override { std::cout << "I am an elephantn"; }
};
然后提供了一种构造具有不同底层实现的Animal
对象的方法。这允许您在std::vector<Animal>
中存储不同类型的Animal
。
相关文章:
- 按基类对象访问派生类资源时出错
- C++ 构造函数传递对基类对象的引用
- 使用基类对象访问派生的仅类方法
- 如何删除派生类中基类对象的新对象
- 使用基类对象调用Dervied Class函数
- 基类对象是否隐式添加到派生类中?
- 如果我有指向基类对象的指针,如何获取虚拟方法的地址?
- 如何不删除基类对象的副本?
- 如何根据基类对象中的变量值分配派生类中的变量?
- 从基类对象的向量中获取特定派生类的对象
- 您可以将派生的类对象作为函数参数代替基类对象吗?
- 如何使用基类对象设置派生类变量的值
- 通过引用派生类对象从基类对象执行向下转换时引发bad_cast异常
- 如何从现有基类对象创建派生类对象
- 子类对象列表重新解释为基类对象列表?(C++11).
- 派生的类指针使用static_cast指向基类对象
- 对我的基类对象数组使用大量的静态类型转换——这可以吗
- 我怎么知道基类对象的指针数组中元素的类型,它将为派生类分配内存
- 在C++中,为什么编译器不了解基类对象在编译时指向哪个对象?
- 为什么可以从实例化基类对象的投射指针调用非静态派生类方法