【问题标题】:Polymorphism in C++ std::list<T>::iteratorC++ 中的多态性 std::list<T>::iterator
【发布时间】:2014-04-29 17:57:50
【问题描述】:

忽略很多细节: 假设我有一个包含函数的抽象 Card 类: virtual int getType()=0;

由同样抽象的GreenCard 派生,其中有一个 virtual int getType()=0; 也是。

那么GreenCard是由定义纯虚的非抽象FollowerItem派生的:

int getType(){ return 1;}

在 Follower 类中和

int getType(){ return 2;}

在 Item 类中。

稍后我创建(并填写)GreenCard 指针列表

list&lt;GreenCard*&gt;* hand;

...我想循环打印手牌(取决于它们的类型):

    list<GreenCard *>::iterator it;

    for(it=hand->begin() ; it!=hand->end() ; ++i){
        tp.getCorrectType(*it);
            ...
    }

在这个函数中,我在第一行得到了 SegFault!

void getCorrectType(GreenCard* card)
{
    /*SF here->*/  if(card->getType()==2){
        ...
    }
}

我确信“卡”已正确创建和初始化,因为在上一行我在 gdb 中写入:p *card ...我可以看到它的所有字段(卡、绿卡和与项目相关的字段——是的,它是一个“项目”)都正确!

编辑:好的,那么这里有更多代码:

class Player{

    list<GreenCard*>*   fateDeck;
    list<GreenCard*>*   hand;
    static const int START_HAND = 4;

    Player(){ 
        fateDeck = new list<GreenCard*> ();
        hand = new list<GreenCard*>();
    }

    void initialize(){
        DeckBuilder db;

        *fateDeck = *(db.createFateDeck() );

        db.deckShuffler(fateDeck);
        initializeHand();
     }

    void initializeHand(){
        for(int counter=0 ; counter<START_HAND ; counter++){
            drawFateCard();
}

    void drawFateCard(){
        hand->push_front(fateDeck->front());
        fateDeck->pop_front();
        cout<<'\n'<<"Drawing from fate deck..."<<'\n'<<endl;
    }

    void Player::printHand(){

        TypeConverter tp;
        list<GreenCard *>::iterator it;

         cout<<"You have " << hand->size()<<" fate cards in hand"<<'\n'
         <<"They are the following:"<<endl;

         for(it=hand->begin() ; it!=hand->end() ; ++it){
             tp.getCorrectType(*it);
             // printing depending on type
         }
    }

    void startingPhase(){
        printHand();
    }
}

class DeckBuilder
{
private:
    list<GreenCard*>* green;

public:
    DeckBuilder();
    list<GreenCard *>* createFateDeck();

    void deckShuffler(list<GreenCard*>* green);
}; 

DeckBuilder :: DeckBuilder()
{  
    green = new list<GreenCard*>();
    srand ( unsigned ( time (NULL) ) );
}

list<GreenCard *>* DeckBuilder :: createFateDeck()
{
    int i;
    for(i=0;i<40;i++)  green->push_back(new Follower());
    return green;
}

void DeckBuilder :: deckShuffler(list<GreenCard*>* green)
{
    vector<GreenCard *> vect;
    list<GreenCard*> ::iterator it;
    for(it = green->begin();it!=green->end();it++)
        vect.push_back((*it));

            random_shuffle ( vect.begin(), vect.end() );

            green->clear();

            vector<GreenCard*>:: iterator it2;
            for(it2 = vect.begin();it2!=vect.end();it2++)
                green->push_back((*it2));
}

最终在 main() 中

Player pl();
pl.initialize();
pl.startingPhase;

以及 printHand() 中的段错误;

【问题讨论】:

  • 你能在你填写列表的地方显示代码吗?以及分段错误输出?
  • 同上。看起来列表中的指针变坏了。您是否可以选择使用智能指针(例如 shared_ptr)而不是原始指针?另外,你没有说tp.getCorrectType()中的tp是什么...
  • 您可能已经删除了列表指向的对象,但您还没有发布填充列表的代码,这可能是您的问题的根源。该对象可能已被删除,这会在您稍后访问该对象时产生 SIGSEV。
  • 也许;或者也许内存已被释放,只是没有其他任何东西覆盖它。我不确切知道您的调试器在这种情况下的行为。
  • @user2409839 - 那么您希望 SO 如何帮助您?你声称你所做的一切都不是错的,但有些事情错的。我们只有您发布的一个循环,显示有效的 C++ 代码和一个函数调用。这真的没有帮助。 Me and my coworker have searched really deep and still cannot justify this segfault, any ideas why this is happening??这是错误的结论。 每一次崩溃都是有道理的。您只是没有找到崩溃发生的原因。

标签: c++ segmentation-fault polymorphism virtual invocation


【解决方案1】:

我已将您提供的信息拼凑在一起。这编译和运行没有分段错误(使用 Visual Studio 2013):

#include "stdafx.h"

#include <algorithm>
#include <iostream>
#include <vector>
#include <list>
#include <ctime>

using namespace std;

class Card
{
public:
    virtual int getType() = 0;
};

class GreenCard : public Card
{
public:
    virtual int getType() = 0;
};

class Follower : public GreenCard
{
public:
    int getType(){ return 1; }
};

class Item : public GreenCard
{
public:
    int getType(){ return 2; }
};

class TypeConverter
{
public:
    void getCorrectType(GreenCard* card)
    {
    if (card->getType() == 1)
        std::cout << "Follower" << std::endl;
        if (card->getType() == 2){
        std::cout << "Item" << std::endl;
    }
}
};

class DeckBuilder
{
private:
    list<GreenCard*>* green;

public:
    DeckBuilder();
    list<GreenCard *>* createFateDeck();

    void deckShuffler(list<GreenCard*>* green);
};

DeckBuilder::DeckBuilder()
{
    green = new list<GreenCard*>();
    srand(unsigned(time(NULL)));
}

list<GreenCard *>* DeckBuilder::createFateDeck()
{
    int i;
    for (i = 0; i < 40; i++)  green->push_back(new Follower());
    return green;
}

void DeckBuilder::deckShuffler(list<GreenCard*>* green)
{
    vector<GreenCard *> vect;
    list<GreenCard*> ::iterator it;
    for (it = green->begin(); it != green->end(); it++)
        vect.push_back((*it));

    random_shuffle(vect.begin(), vect.end());

    green->clear();

    vector<GreenCard*>::iterator it2;
    for (it2 = vect.begin(); it2 != vect.end(); it2++)
        green->push_back((*it2));
}

class Player{
    public:
    list<GreenCard*>*   fateDeck;
    list<GreenCard*>*   hand;
    static const int START_HAND = 4;

    Player(){
        fateDeck = new list<GreenCard*>();
        hand = new list<GreenCard*>();
    }

    void initialize(){
        DeckBuilder db;

        *fateDeck = *(db.createFateDeck());

        db.deckShuffler(fateDeck);
        initializeHand();
    }

    void initializeHand(){
        for (int counter = 0; counter < START_HAND; counter++){
            drawFateCard();
        }
    }

    void drawFateCard(){
        hand->push_front(fateDeck->front());
        fateDeck->pop_front();
        cout << '\n' << "Drawing from fate deck..." << '\n' << endl;
    }

    void Player::printHand(){

        TypeConverter tp;
        list<GreenCard *>::iterator it;

        cout << "You have " << hand->size() << " fate cards in hand" << '\n'
            << "They are the following:" << endl;

        for (it = hand->begin(); it != hand->end(); ++it){
            tp.getCorrectType(*it);
            // printing depending on type
        }
    }

    void startingPhase(){
        printHand();
    }


};

int _tmain(int argc, _TCHAR* argv[])
{
    Player pl;
    pl.initialize();
    pl.startingPhase();
    return 0;
}

请提供一个小的独立示例来演示错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-23
    • 2017-12-09
    • 2012-06-16
    • 1970-01-01
    • 2022-11-21
    • 1970-01-01
    • 2017-04-21
    • 2017-08-13
    相关资源
    最近更新 更多