2013-01-03 48 views
2

我有這樣的代碼:繼承和memcpy - 它是如何一起工作的?

#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->打印(): 是c前行成了老虎爲何還打印了我這一行: 羅斯用速度135081 insted的的 羅斯與速度3 爲什麼有內存問題? 它爲什麼叫老虎而不是貓的打印方法?

+0

一隻貓不能成爲老虎! –

回答

10

不是一起工作。

在這些對象上使用memcpy產生未定義的行爲,標準允許任何事情發生。

這不是繼承本身導致您的問題,而是存在虛擬成員函數或自定義構造函數/析構函數。這些使您的物體丟失可分級複製分類要求使用memcpy時。

你的類不是第二個原因平凡的,可複製 - 它含有std::string類型的成員這是不平凡的,可複製

實際上,當您執行std::string子對象的按位副本時,最終會有兩個指向同一內存的指針,並且這兩個對象都將嘗試釋放此指針。這會讓程序崩潰。如果在v表上使用memcpy尚未如此。

但是,當你混合優化,甚至可以發生奇怪的事情。這就是未定義的行爲的意思。

+1

是的,但是有內存問題? –

+0

該問題比內存問題更糟糕。它是*未定義的行爲*這意味着問題可能包括內存,數據損壞,重新格式化硬盤驅動器,破壞您的SO配置文件... –

3

您應該避免在c++中使用memcpy作爲對象,而是使用複製構造函數。