3

我有这个代码:

#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 变成老虎之前的行,为什么它打印我这一行:Ross with speed 135081 insted of Ross with speed 3 为什么存在内存问题?为什么它调用的是 Tiger 而不是 cat 的 print 方法?

4

2 回答 2

10

不能一起工作。

memcpy在这些对象上使用会产生未定义的行为,标准允许任何事情发生。

导致问题的不是继承本身,而是虚拟成员函数或自定义构造函数/析构函数的存在。这些使您的对象失去使用memcpy.

你的类不是trivially-copyable的第二个原因 - 它包含一个 type 的成员std::stringnot trivially-copyable

实际上,当您执行std::string子对象的按位复制时,您最终会得到两个指向同一内存的指针,并且两个string对象都会尝试释放该指针。那会让你的程序崩溃。如果memcpy在 v-table 上使用之前没有这样做。

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

于 2013-01-03T13:14:54.183 回答
3

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

于 2013-01-03T13:16:12.533 回答