2014-04-22 9 views
0

우리는 여러 종류의 동물 클래스를 상속하는 동물 클래스를 만들 것이라고 가정합니다. 즉 Dog 클래스는 Mammal 클래스에서 상속받을 Carnivore 클래스를 상속합니다. 내 자신의 주된 기능으로 수업을 사용 해보려고했고, 그들이 말하는 것과 그 이름을 인쇄했지만 선생님의 주 파일로 수업을 실행할 때 덤핑 스택 추적을 알려줍니다.왜 코드를 실행하면 스택 덤프 오류가 발생합니까?

#include <iostream> 
#include <string> 
#include <typeinfo> 
#include <vector> 

using namespace std; 

class Mammal { 
public: 
    virtual string say() = 0; 
    virtual string name() = 0; 
}; 

class Carnivore : public Mammal { 
public: 
    virtual string say() = 0; 
    virtual string name() = 0; 
}; 

class Canid : public Carnivore{ 
public: 
    virtual string say() = 0; 
    virtual string name() = 0; 
}; 

class Dog : public Canid{ 
public: 
    string say(){ 
     return "bark"; 
    } 
    string name(){ 
     return "dog"; 
    } 
}; 

class Fox : public Canid{ 
public: 
    Fox(){ 
     spoke = "ay"; 
    } 
    std::string say(){ 
     spoke += spoke; 
     return spoke; 
    } 
    std::string name(){ 
     return "fox"; 
    } 
private: 
    std::string spoke; 
}; 

class Feline : public Canid{ 
public: 
    virtual string say() = 0; 
    virtual string name() = 0; 
}; 

class Cat : public Feline{ 
public: 
    std::string say(){ 
     return "moew"; 
    } 
    std::string name(){ 
     return "cat"; 
    } 
}; 

class Rodent : public Mammal{ 
public: 
    virtual string say() = 0; 
    virtual string name() = 0; 
}; 

class Mouse : public Rodent{ 
public: 
    std::string say(){ 
     return "squeak"; 
    } 
    std::string name(){ 
     return "mouse"; 
    } 
}; 

Mammal* MammalFactory(const std::type_info& ti){ 

    if(ti == typeid(Dog)){ 
     cout << "running dog" << endl; 
     Dog D; 
     Mammal* dog = &D; 
     return dog; 
    } 
    else if (ti == typeid(Fox)){ 
     cout << "running fox" << endl; 
     Fox F; 
     Mammal* fox = &F; 
     return fox; 
    } 
    else if (ti == typeid(Cat)){ 
     cout << "running cat" << endl; 
     Cat C; 
     Mammal* cat = &C; 
     return cat; 
    } 
    else if (ti == typeid(Mouse)){ 
     cout << "running mouse" << endl; 
     Mouse M; 
     Mammal* mouse = &M; 
     return mouse; 
    } 
    else{ 
     return NULL; 
    } 
} 

int main(){ 

    int score = 90; 
    std::vector<Mammal*> mammals; 
    mammals.push_back(MammalFactory(typeid(Dog))); 
    mammals.push_back(MammalFactory(typeid(Cat))); 
    mammals.push_back(MammalFactory(typeid(Mouse))); 
    Mammal* fox = MammalFactory(typeid(Fox)); 

    mammals.at(0)->name(); 

    for (std::vector<Mammal*>::iterator I = mammals.begin(); I != mammals.end(); ++I) { 
     std::cout<<(*I)->name()<<" goes "<<(*I)->say()<<'\n'; 
    } 

    //Check animal names 
    if (mammals.at(0)->name() != "dog") { 
     std::cout<<"Dog's name is incorrect! -10\n"; 
     score -= 10; 
    } 
    if (mammals.at(1)->name() != "cat") { 
     std::cout<<"Cat's name is incorrect! -10\n"; 
     score -= 10; 
    } 
    if (mammals.at(2)->name() != "mouse") { 
     std::cout<<"Mouse's name is incorrect! -10\n"; 
     score -= 10; 
    } 
    if (fox->name() != "fox") { 
     std::cout<<"Fox's name is incorrect! -10\n"; 
     score -= 10; 
    } 

    //Fox part 

    std::string thing1 = fox->say(); 
    std::string thing2 = fox->say(); 

    std::cout<<"What does the "<<fox->name()<<" say?\n"; 
    std::cout<<thing1<<"!\n"; 
    std::cout<<thing1<<"!\n"; 
    std::cout<<thing1<<"!\n"; 
    std::cout<<"What does the "<<fox->name()<<" say?\n"; 
    std::cout<<thing2<<"!\n"; 
    std::cout<<thing2<<"!\n"; 
    std::cout<<thing2<<"!\n"; 

    if (thing1 == thing2) { 
     std::cout<<"Foxes don't say the same thing twice!\n"; 
     score -= 10; 
    } 

    for (std::vector<Mammal*>::iterator I = mammals.begin(); I != mammals.end(); ++I) { 
     delete *I; 
    } 
    delete fox; 
    return 0; 
} 
+0

게시 할 수 있습니까? – Nathan

답변

0

소멸자가 가상이 아니며, 로컬 변수의 주소를 반환합니다. 이것은 정의되지 않은 동작입니다.

Mammal* MammalFactory(const std::type_info& ti) 
{ 
    if(ti == typeid(Dog)) 
    { 
     cout << "running dog" << endl; 
     Dog D; 
     Mammal* dog = &D; 
     return dog; // so what happens to D when MammalFactory returns? 
    } 
} 

다른 모든 파생 클래스에 대해 이와 동일한 실수를 범합니다. 함수가 반환되면 더 이상 "D"가 없습니다. 그것은 연기가 퍼지면서 더 이상 존재하지 않는이 변수의 주소를 반환합니다.

새 포유 동물 (return new Dog;)을 만들거나 개를 만들고 로컬이 아닌 것을 반환하는 방법을 제안하십시오. (다시, 문제는이 클래스에만 국한되지 않지만 다른 모든 클래스).

+0

당신의 제안으로 새로운 포유 동물을 만들었습니다. – user3492502

+0

@ user3492502 : 여우 나무 껍질을 30 번 말하게하려고 할 수 있습니다. –

0

일부 문제 :

  • 기본 클래스에서 가상 소멸자 부족.
  • 매달 포인터을 반환하면 존재하지 않는 로컬 객체에 대한 포인터입니다.
  • 여우의 메모리 소비량이 엄청나게 증가합니다.