У меня есть этот код:
#include <iostream>
#include <string>
#include <cstring>
class Animal
{
public:
Animal(const std::string &name) : _name(name)
{
}
virtual void Print() const = 0;
virtual ~Animal() {}
protected:
std::string _name;
};
class Dog : public Animal
{
public:
Dog(const std::string &name, const std::string &dogtype) : Animal(name), _dogtype(dogtype)
{
Print();
}
void Print() const
{
std::cout << _name << " of type " << _dogtype << std::endl;
}
private:
std::string _dogtype;
};
class Cat : public Animal
{
public:
Cat(const std::string &name, int weight) : Animal(name), _weight(weight)
{
Print();
}
virtual void Print() const
{
std::cout << _name << " of weight " << _weight << std::endl;
}
virtual ~Cat(){}
private:
int _weight;
};
class Tiger : public Cat
{
public:
Tiger(const std::string &name, int weight, double speed) : Cat(name, weight), _speed(speed)
{
Print();
}
void Print() const
{
std::cout << _name << " speed " << _speed << std::endl;
}
virtual ~Tiger(){std::cout << "Tiger's dtor" << std::endl;}
private:
int _speed;
};
int main()
{
Animal *a = new Tiger("theRealKing", 3, 40.5);
Cat *c = new Cat("silvester", 4);
memcpy(c, a, sizeof(Cat));
c->Print(); /// ------------------------
delete a;
delete c;
return 0;
}
в строке: c-> Print ():
линия до этого c стала тигром, так почему он печатает мне эту строку:
Росс со скоростью 135081
поставленный
Росс со скоростью 3
почему проблема с памятью?
почему он вызывает метод печати тигра, а не кота?
Это не работать вместе.
С помощью memcpy
на этих объектах производит неопределенное поведение, Стандарт разрешает что угодно.
Проблемы вызывают не наследование как таковое, а наличие виртуальных функций-членов или собственного конструктора / деструктора. Это заставляет ваши объекты терять тривиальный-копируемый классификация, которая требуется когда используешь memcpy
,
Ваш класс не тривиальный-копируемый по второй причине — он содержит член типа std::string
который не тривиальный-копируемый.
На практике, когда вы выполняете побитовую копию std::string
подобъект, в итоге вы получите два указателя на одну и ту же память, и оба string
объекты будут пытаться освободить этот указатель. Это приведет к краху вашей программы. При использовании memcpy
на V-стол не сделал этого раньше.
Но когда вы смешиваетесь с оптимизацией, могут произойти даже более странные вещи. Это то что неопределенное поведение средства.
Вы должны избегать использования memcpy для объектов в c++
используйте вместо этого конструктор копирования.