继承和记忆-它们是如何一起工作的

inheritance and memcpy - How is it work together?

本文关键字:一起 工作 何一起 记忆 继承      更新时间:2023-10-16

我有这样的代码:

#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是必需的

你的类不是trivial -copyable的第二个原因——它包含一个类型为std::string的成员,它不是trivial -copyable

实际上,当您执行std::string子对象的位拷贝时,您最终会得到指向同一内存的两个指针,并且两个string对象都会尝试释放这个指针。这会使你的程序崩溃。如果在v表上没有使用memcpy

但是当你混合优化时,甚至会发生更奇怪的事情。这就是未定义行为的含义。

您应该避免对c++中的对象使用memcpy,而应使用复制构造函数。