I am having a problem copying data members from an inherited class to the base class. All of the data is copied except the container data.

#ifndef NPC_H
#define NPC_H

/*
 * Basic parent to all other NPC types.
 * NOTICE: player is considered an NPC type
 */

enum CLASS_TYPE{
     CT_CLERIC = 0,
     CT_MAGICUSER,
     CT_FIGHTER
};
class NPC
{
    private:
        string name;
        CLASS_TYPE npcclass;
        int level;
        int strength;
        int intelligence;
        int wisdom;
        int dexterity;
        int constitution;
        int charisma;
        int armorclass;
        int hitpoints;
        int maxhp;
        int gold;
        int experience;
        int maxxp;
        
        int deathray;
        int poison;
        int magicwands;
        int paralysis;
        int turntostone;
        int dragonbreath;
        int rods;
        int staves;
        int spells;
        
        WEAPON weapon;
        ARMOR armor;
        SHIELD shield;
        
        bool hasshield;
        bool istwohanded;

        ITEM* inventory[15];
        vector<SPELL> castableSpells;
        
	public:
		// class constructor
		NPC();
		// class destructor
		~NPC();
		
		void DisplayStats();
		
		string GetName();
        void SetName(string newname);
        
        CLASS_TYPE GetClass();
        void SetClass(CLASS_TYPE newnpcclass);
        
        int GetLevel();
        void SetLevel(int amount);
        
        int GetSTR();
        void SetSTR(int amount);
        
        int GetINT();
        void SetINT(int amount);
        
        int GetWIS();
        void SetWIS(int amount);
        
        int GetDEX();
        void SetDEX(int amount);
        
        int GetCON();
        int SetCON(int amount);
        
        int GetCHR();
        void SetCHR(int amount);
        
        int GetAC();
        int SetAC(int amount);
        
        int GetHP();
        void SetHP(int amount);
        void AddHP(int amount);
        void LoseHP(int amount);
        
        int GetMHP();
        void SetMHP(int amount);
        
        int GetGold();
        void SetGold(int amount);
        void AddGold(int amount);
        void LoseGold(int amount);
        
        int GetXP();
        void SetXP(int amount);
        void AddXP(int amount);
        void LoseXP(int amount);
        
        int GetMXP();
        void SetMXP(int amount);
        
        
        WEAPON* GetWeapon();
        void SetWeapon(WEAPON newweapon);
        
        ARMOR* GetArmor();
        void SetArmor(ARMOR newarmor);
        
        SHIELD* GetShield();
        void SetShield(SHIELD* nshield);
        
        bool GetIsTwohanded();
        void SetIsTwohanded(bool yesno);
        
        bool AddInventory(ITEM* item);
        ITEM** GetInventorylist();
        
        void AddSpell(SPELL *newspell);
        vector<SPELL>* GetSpellList();
        
        void SetSavingsThrows(int svOne, int svTwo, int svThree, int svFour, int svFive);
};

#endif // NPC_H
#ifndef MAGICUSER_H
#define MAGICUSER_H

#include "npc.h" // inheriting class's header file

/*
 * No description
 */
class MAGICUSER : public NPC
{
	public:
		// class constructor
		MAGICUSER();
		// class destructor
		~MAGICUSER();
};

#endif // MAGICUSER_H
#include "Library.h"
#include "magicuser.h" // class's header file

// class constructor
MAGICUSER::MAGICUSER()
{
    SetName("Magic-User"); // name
    SetClass(CT_MAGICUSER); //npcclass
    SetLevel(1); //level
    SetSTR(8); //strength
    SetINT(17); //intelligence
    SetWIS(11); //wisdom
    SetDEX(16); //dexterity
    SetCON(14); //constitution
    SetCHR(9); //charisma
    SetHP(4); // hitpoints
    SetMHP(4); // maxHP
    SetGold(200); //gold
    SetXP(0); //xp
    SetMXP(2000);
    
    SetSavingsThrows(13, 14, 13, 16, 15);
    
    WEAPON* wp = GetWeapon();
    wp->SetName("Dagger");
    wp->SetDamage(4);
    wp->SetIsTwohanded(false);
    SetIsTwohanded(wp->GetIsTwohanded());
    
    ARMOR* ar = GetArmor();
    ar->SetName("Cloth Armor");
    ar->SetAC(2);
    
    SHIELD* sh = GetShield();
    sh->SetName("No Shield");
    sh->SetAC(0);
    
    SetAC((9 - ar->GetAC()) - sh->GetAC()); //armorclass
    
    MAGICMISSILE magicmissile;
    AddSpell(&magicmissile);  //<- NOTICE: in base class vector is empty
}

// class destructor
MAGICUSER::~MAGICUSER()
{
	// insert your code here
}

Now all of the Gets/Sets are appropriate to the data members. one returns a copy of the value, and one sets the value to an amount of the correct type. NOTICE: the last data member in the NPC class is a container. When I create an instance of a MAGICUSER class it comes with a spell added to the vector. However, the base class castableSpells.size() = 0;
How could I add that spell when I copy the MAGICUSER to the NPC class?

NPC player;
MAGICUSER mu;
player = mu;

I have read about operator overloads and handle classes in C++ PRIMER 4th ed. but I'm getting lost really. any advice?.

Recommended Answers

All 14 Replies

Certainly you can pare this down to < 20 lines or so with a main function that will show us the problem.

Dave

PROBLEM:
all of the data members of the derived class are copied over to the main class EXCEPT the container values.

MAGICUSER mu; //mu has a spell inside its castableSpells vector
NPC player; //player's castableSpells vector is empty
player = mu; //when copied, player's castableSpells is still empty

All of the data is copied except the container data.

What do you mean by the "container data"?

Now all of the Gets/Sets are appropriate to the data members. one returns a copy of the value, and one sets the value to an amount of the correct type.

Normally "Get" functions like these (which return pointers) do not do any copying. They return the pointer and that's it.

WEAPON* wp = GetWeapon();    
    ARMOR* ar = GetArmor();    
    SHIELD* sh = GetShield();

Depending on your design, your "Set" functions would also take pointers for arguments in these functions, not objects themselves, and the data members themselves are very often pointers. You have them as objects, not pointers:

WEAPON weapon;
ARMOR armor;
SHIELD shield;

There could be perfectly good reasons for doing it this way, but concepts like "copying" need to take considerations like this in mind (pointers versus the objects themselves, shallow versus deep copying of the class data members.


NOTICE: the last data member in the NPC class is a container.

vector<SPELL> castableSpells;

This is the container you spoke of earlier? This is what is not working?


You have a vector of objects here (not pointers). To make a deep copy, I imagine you'd want to create a new vector, then loop through the original vector, make a deep copy of that SPELL, then push that new SPELL onto the new vector.

As you have not posted the copy functions, it's hard to say where exactly the problem is.

Looks like you edited the post while I was composing mine.

This is a bit unorthodox (but potentially could be OK). Your "Set" function takes an object, but your "Get" function returns a pointer.

ARMOR* GetArmor();
void SetArmor(ARMOR newarmor);

Normally I'd expect to see this:

ARMOR* GetArmor();
void SetArmor(ARMOR* newarmor);

I brought that up in the last post, I think. It may or may not have anything to do with your present problem (I would imagine it doesn't), but since you are talking about copying, the difference can have important ramifications.

here are the NPC's functions that were not included

void NPC::AddSpell(SPELL *newspell){
    if(castableSpells.size() > 0){
	for (vector<SPELL>::iterator IT = castableSpells.begin(); IT != castableSpells.end(); IT++){
            if(IT->GetName() == newspell->GetName()){
                IT->AddQuantity(1);
                return;
            }
        }
    }
    switch (newspell->GetSpellType()){
	case ST_GENERIC:{
		castableSpells.push_back(new SPELL(newspell));
		break;
	}
	case ST_MAGICMISSILE:{
		castableSpells.push_back(new MAGICMISSILE((MAGICMISSILE*)newspell));
		break;
	}
    }
    return;
}
vector<SPELL>* NPC::GetSpellList(){
    return &castableSpells;
}

EDIT:
since the NPC's castableSpells container is empty and the MAGICUSER's container has a spell push_back()'ed, would I construct an operator overload in the NPC class to handle copying the MAGICUSER to the NPC? if so how would it look?

VernonDozier, am I crazy or are those two code snippets identical?

Dave

VernonDozier, am I crazy or are those two code snippets identical?

Dave

No, you're not crazy. I copied and pasted and posted and forgot to make the change. See the edited post.:)

maybe I am going about this the wrong way. Let me just post the bigger picture and maybe you'll find my ignorance higher up in the logic of my game.

I create the original team(crew) that the user (player) is going to use during the game. I then send those 3 over to the CreatPlayers method so the player can choose a type of player to be copied and the other 2 types are copied to the other objects of the team(crew). I copy the class types to the NPC type because the actual MAGICUSER, CLERIC, and FIGHTER types are instantiated in the CreatePlayers method and will be destroyed when the method is exited

int main(){
    //NOTE: this may be moved out of main to the opening scene method
    //where game starts
    NPC player;
    NPC compPlayerOne;
    NPC compPlayerTwo;
    
    CreatePlayers(player, compPlayerOne, compPlayerTwo); //arguments are references
    player.SetName("Dartania");
    compPlayerOne.SetName("Roland");
    compPlayerTwo.SetName("Cyndy");

    vector<NPC> crew; //put team in a vector to handle as a whole
    crew.push_back(player);
    crew.push_back(compPlayerOne);
    crew.push_back(compPlayerTwo);
    
    DisplayCrew(&crew);
}
void CreatePlayers(NPC &player, NPC &compPlayerOne, NPC &compPlayerTwo){     
    FIGHTER fighter;  //NOTE: these objects are destroyed when 
    CLERIC cleric;    //this method exits
    MAGICUSER mu;

    fighter.DisplayStats();
    cleric.DisplayStats();
    mu.DisplayStats();
    
    CLASS_TYPE t = ChooseClass();
    switch(t){
        case CT_FIGHTER:
            player = fighter;        //must copy them because
            compPlayerOne = cleric;  //original objects are destroy
            compPlayerTwo = mu;      //when method exits
            break;
        case CT_CLERIC:
             player = cleric;
             compPlayerOne = fighter;
             compPlayerTwo = mu;
             break;
        case CT_MAGICUSER:
             player = mu;
             compPlayerOne = fighter;
             compPlayerTwo = cleric;
             break;
        default:
             player = fighter;
             compPlayerOne = cleric;
             compPlayerTwo = mu;
             break;
    }
}

So is it this?

vector<SPELL> castableSpells;

or this:

vector<SPELL*> castableSpells;

or this?

vector<SPELL>* castableSpells;

or this?

vector<SPELL*>* castableSpells;

It's pretty important and it looks like it's changing from post to post.

Next, you need to post the code where you are actually copying the castableSpells vector, since that's where the problem is, correct?

Before you copy it, check the size of the original vector. Have you confirmed that THAT vector isn't empty. If so, then you have a problem BEFORE the copying that you need to solve first.

It looks like this is code that someone has provided you as a skeleton. That's fine, but it's something we need to know, since we need to know what code is yours and what code is allowed to be changed and what code isn't.

I would refrain from storing a pointer to a vector of pointers if possible. If this is a small application, I don't see a reason not to just store the data like this:

vector<SPELL> castableSpells;

That will certainly make things much much easier.

Dave

All the code is mine. I am the sole author of this code. I find it rude that you assume that someone would provide this buggery work. As you have stated somewhat hidden in your text behind the lines, that I am ignorant when it comes to passing proper argument the proper way. I am still new to C++ so please be kind and assume that I ignorant but not stupid. VERNON you question where I am copying the vector over right? well I assuming (if it could) that the spells would be copied over when
NPC player;
MAGICUSER mu;
player = mu;
but it's not because I think the NPC's is empty;

EDIT:

would refrain from storing a pointer to a vector of pointers if possible. If this is a small application, I don't see a reason not to just store the data like this:

vector<SPELL> castableSpells;

That will certainly make things much much easier.

Dave

if you look in the NPC class that is how they are stored. you can get pointer to the beginning of that list with

vector<SPELL>* GetSpellList();

and you can add a spell directly to the list

void AddSpell(SPELL *newspell);

All the code is mine. I am the sole author of this code. I find it rude that you assume that someone would provide this buggery work. As you have stated somewhat hidden in your text behind the lines, that I am ignorant when it comes to passing proper argument the proper way. I am still new to C++ so please be kind and assume that I ignorant but not stupid. VERNON you question where I am copying the vector over right? well I assuming (if it could) that the spells would be copied over

No one's accusing you of cheating or being stupid. It was a simple question and not accusatory or rude at all. Often on these types of assignments either an instructor is providing a skeleton and then you add the rest of the code or the book is. There's nothing wrong with it, but we need to know so we don't tell you to change the skeleton code which you usually aren't allowed to change. Code like this suggested a skeleton:

// class destructor
MAGICUSER::~MAGICUSER()
{
	// insert your code here
}

Yes, you do strike me as ignorant as to how to pass arguments correctly, but ignorance is not to be considered a perjorative and I never assume that ignorance means stupidity. It means you are a beginner, as we all were, and that you aren't yet clear on how to design your functions regarding pointers, which is to be expected. None of us start out understanding these things. They aren't trivial. My questions were intended to clarify and to raise some important issues to you. There's no agenda, either hidden or overt, to make you look dumb and make fun of you.

The point is that, however you do it, and daviddoria's suggestion that you do it this way seems logical:

vector<SPELL> castableSpells;

you have to make sure things match, so if you take his suggestion, which was your original design in the first place I believe, stuff like this won't work:

castableSpells.push_back(new SPELL(newspell));

because you pushing a SPELL* onto the vector rather than a SPELL.

thanks for the info.
I think I need to rehash passing arguments again. Thanks for the advice.

pls i need examples of a code block for a class with a virtual function

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.