-2

I'm trying to write a Class that defines the stats from a champion/character and I want to initialize "champions" with name, id, hp, ... in the Class My question is how do I do that? Do I need another class or do I define objects in the class which I did ?

#include <iostream>
using namespace std;


class ChampionStats {
    private:
        
    int m_id;
    string m_name;           // champion ID and Stats
    int m_hp;
    int m_ad;

    public:
        
    ChampionStats(int id, string name, int hp, int ad) {
        m_id = id;
        m_name = name;                  // initialize Champion
        m_hp = hp;
        m_ad = ad;
    }
    
    void printChamp() {                     // print champion stats 
        cout << "ID: "   << m_id  << endl
             << "Name: " << m_name << endl                      
             << "HP: "   << m_hp << endl
             << "AD: "   << m_ad << endl;
    }
};

int main() {
       
    return 0;
}
phos
  • 19
  • 4
  • 2
    what do you mean by `predefine`? – vmp Jan 25 '21 at 22:38
  • 2
    1. What exactly do you mean by "pre-define champions"? Do you want your `class ChampionStats` instances to be usable at compile-time? 2. [Don't use `using namespace std`](https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice) 3. Use an [initializer list](https://www.learncpp.com/cpp-tutorial/constructor-member-initializer-lists/) in your constructor. – einpoklum Jan 25 '21 at 22:41
  • 2
    `ChampionStats Fred(1, "Fred" 42, 96);`? – user4581301 Jan 25 '21 at 22:42
  • Sorry for the misunderstanding, for example I want a Champion Id = 01 , Name = "Udyr", HP = 1000, ... basically initializing a Champion in the class without doing it in the main function, so I have described Champs ready I can print out. – phos Jan 25 '21 at 22:45
  • 1
    `std::vector prefab = {{1, "Fred", 42, 96}, {2, "Abby", 88, 11}, {3, "Stinky", 18, 77}};`? – user4581301 Jan 25 '21 at 22:53
  • @user4581301 yes something like that, I thought about creating a object in the class and describe it like { m_id = 001; m_name = "Fred"; m_hp = 88; m_ad = 34; }Fred; Is that possible ? Or is your Method easier to read and write ? – phos Jan 25 '21 at 23:02
  • Lightbringer, I am still unsure of exactly what you are asking. Your most recent comment appears as though you are looking for [Aggregate Initializers with Designated Initializers](https://en.cppreference.com/w/cpp/language/aggregate_initialization#Designated_initializers), something that was formally added to the language in last year's C++ Standard revision. – user4581301 Jan 25 '21 at 23:16
  • @user4581301 Im sorry I really dont know how i can describe it to you, I want finished Champions in my class but i dont know how to do it like in this screenshot thats my idea:http://prntscr.com/xmi84w – phos Jan 25 '21 at 23:22
  • What you're trying to get is not nearly as useful as you'd like. `Fred` [would have to be `static`](https://en.cppreference.com/w/cpp/language/static) or he'd be duplicated in every instance of `ChampionStats` you created (and that would get recursive: `Fred` contains `Fred` contains `Fred`...) and with a few exceptions, `static` members need to be defined outside the class so you're right back where you started. – user4581301 Jan 25 '21 at 23:46
  • Give this a try: Define a bunch of variables with [Static storage duration](https://en.cppreference.com/w/cpp/language/storage_duration#Storage_duration) and stick them in a namespace. – user4581301 Jan 25 '21 at 23:47
  • @user4581301 alright thanks, gonna stick to your advice – phos Jan 26 '21 at 01:24

1 Answers1

0

It's far too annoying to attempt to define ChampionStats instances inside the ChampionStats class. They would have to be made static or every instance would contain all of the pre-built champions. That includes the pre-built champions themselves, and that's a particularly nasty bit of recursion that the compiler's going to shut right down.

But if you make them static, you're back to defining the instances outside of the class.

Instead I pitch a namespace as a simple direct solution.

namespace champions
{
    ChampionStats Fred  ({1, "Fred",   42, 96);
    ChampionStats Abby  ({2, "Abby",   88, 11);
    ChampionStats Stinky({3, "Stinky", 18, 77);
}

But a container might scale a bit better.

int nextId = 0; // keep track of the next available ID
map<string, ChampionStats> champs =
{
 {"Fred",   {++nextId, "Fred",   42, 96}},
 {"Abby",   {++nextId, "Abby",   88, 11}},
 {"Stinky", {++nextId, "Stinky", 18, 77}},
};

You can keep adding rows to the list until the cows come home and nothing else needs to change.

Usage:

int main()
{
    champs.at("Fred").printChamp();
    champs.at("Abby").printChamp();
}

But it's clunky. The name is repeated twice, making it really easy to typo or cut-n-paste-n-forget. There's probably a better way to pull this off with some groovy template voodoo, but I'm no wizard. Here I'd use a macro.

int nextId = 0; // keep track of the next available ID
#define BUILD_CHAMP(name, hp, ad) {name,{++nextId, name, hp, ad}}
map<string, ChampionStats> champs =
{
 BUILD_CHAMP("Fred",   42, 96),
 BUILD_CHAMP("Abby",   88, 11),
 BUILD_CHAMP("Stinky", 18, 77),
};
user4581301
  • 33,082
  • 7
  • 33
  • 54