In fact, look at the Sword and Dagger classes in your first post. They both have no new member variables. Sword does literally nothing - you've just got the class there as a way of encoding values for the health/power/value/weight. Dagger's the same, except that it has a viewAttributes method - which, except for the word 'dagger' in it, would not look out of place in the base Weapon class.
The primary disadvantage to this is that whenever you want to change the details for a weapon, or add/delete a weapon, you have to rebuild your code. It also means that code changes to the base 'weapon' class might have to be accounted for by updating every individual other class...
The less code you write, the less opportunity there is for you to write it incorrectly.
It would be better if you went for a data-driven approach. First, you extend the 'Weapon' class to include the name of the weapon, and the code for displaying it, like this:
class Weapon{ std::wstring name; int health, power, value, weight; public: void displayAttributes() const { std::cout << name << ": Attributes:" << std::endl; std::cout << "Health: " << health << " %" << std::endl; std::cout << "Power: " << health * power << std::endl; std::cout << "Value: " << value << " gold" << std::endl; std::cout << "Weight: " << weight << " kilograms" << std::endl; }
Then we'll extend the class to be able to load its data from a file, like so:
static Weapon* FromFile(ifstream& input) { Weapon* wp = new Weapon(); getline(input, wp->name); input >> wp->health >> wp->power >> wp->value >> wp->weight; }};
FromFile will read a single weapon from a text file that looks something like:
Samurai Sword100 20 5 2Dagger30 5 1 1
So you can define all the weapons, and tweak them all, just by editing that file. You don't even need to rebuild the game, you just run it with the new file.
Lastly, it would be convenient that once you've loaded a weapon you can store it somewhere useful, and, given that these are 'templates' for weapons, create instances of each weapon. Let's create a WeaponLibrary:
class WeaponLibrary{ private: std::map<std::wstring, Weapon*> weapons; protected: WeaponLibrary() {} public: ~WeaponLibrary() { for(std::map<std::wstring, Weapon*>::iterator it = weapons.begin(); it != weapons.end(); ++it) { delete (*it).second; } } public: static WeaponLibrary* FromFile(const std::string& filename) { WeaponLibrary* result = new WeaponLibrary(); ifstream infile(filename); while(!infile.eof()) { Weapon* wp = Weapon::FromFile(infile); result->weapons[wp->name] = wp; } return result; } public: Weapon* CreateByName(const std::wstring& name) { Weapon* prototype = weapons[name]; return new Weapon(*prototype); }};
WeaponLibrary is created by calling WeaponLibrary::FromFile, and giving it the name of the file storing all the weapon data. It loads in all the weapons, creating an instance of each one. When you ask it to give you a new weapon, you give it the name of the 'template' you want to use; it finds that weapon, and then creates a copy of it which it returns to you.