class Base
{
public:
static int GetType_S()
{
return 1;
}
virtual int GetType()
{
return GetType_S();
}
};
class Son1 : public Base
{
public:
static int GetType_S()
{
return 2;
}
virtual int GetType()
{
return GetType_S();
}
};
My Question is : When I need some other classes like "Son1,Son2..." ,every class should implement GetType and GetType_S function, This two functions is repeated.So How to design this classes gracefully to let son classes implement only one function?And It is best not to use macros.
You can have a class template that each SonN inherits from, which in turn inherits Base.
template <int Type>
class Middle : public Base
{
public:
static int GetType_S()
{
return Type;
}
virtual int GetType()
{
return GetType_S();
}
};
class Son1 : public Middle<2> {};
class Son2 : public Middle<3> {};
class Whatever : public Middle<42> {};
Or, if there is nothing else in those classes:
using Son1 = Middle<2>;
using Son2 = Middle<3>;
using Whatever = Middle<42>;
I'm working on a game and I want to make a base Actor class that holds Stat values that are shared among a variety of Actor types, but I'm having an issue understanding how I can accomplish this without having the base class having a different Stats variable than the actor types...
This is exactly what I have made right now (as shown in the code)... However, I want to somehow make the BaseActor "stats" type become either a PlayerStats or a MonsterStats object when it is created...This way the PlayerActor and MonsterActor no longer need the different "monster_stats" and "player_stats" objects as they inherit the correct type from BaseActor. Is this possible? I'm thinking it can be done through templates, but I'm not too versed in those.
class BaseStats {
public:
int defense;
private:
};
class MonsterStats : public BaseStats {
public:
int drop_rate;
private:
};
class PlayerStats : public BaseStats {
public:
int attack_power;
private:
};
class BaseActor {
public:
BaseStats stats;
private:
};
class MonsterActor : public BaseActor {
public:
MonsterStats monster_stats;
private:
};
class PlayerActor : public BaseActor {
public:
PlayerStats player_stats;
private:
};
Have PlayerStats and MonsterStats derive from BaseStats. Have the constructor of each derived BaseActor allocate the stats with:
MonsterActor::MonsterActor()
{
m_stats = make_shared<MonsterStats>();
}
and have
std::shared_ptr<BaseStats> m_stats;
in the base class.
Look for Jeffrey's answer for a better way. But since you wanted to do this through templates (which is not recommended): -
template <typename T>
class BaseActor {
public:
T stats;
};
class MonsterActor : public BaseActor<MonsterStatus> {
public:
};
class PlayerActor : public BaseActor<PlayerStatus> {
public:
};
I have this code for a basic entity system I'm testing
Enity.h
class Enemy
{
public:
void attack(Player player);
virtual void die();
protected: //Info variables
int attackDamage;
std::string name;
bool alive;
}
class ChildEnemy1 : public Enemy
{
name = "Enemy1" //Invalid
};
class ChildEnemy2 : public Enemy
{
name = "Enemy2" // Invalid
};
How would you change the Info variables (attackDamage, name, alive) without inheriting a public setter function
(retain encapsulation).
EDIT: This is not a duplicate question as I have not found an adequate answer to this problem on SO
Initialize the members in the constructor.
class ChildEnemy1 : public Enemy
{
ChildEnemy1() : name("Enemy1") {}
};
How can I prevent a public member to be inherited by it's derived class? Like, if I have this:
class Person {
public:
enum { MALE, FEMALE, BOTH };
Person(std::string name, int gender)
: _name(name)
{
switch (gender) { /* processing here */ }
}
protected:
std::string _name;
};
class Male : public Person {
public:
Male(std::string name)
: _name(name, 0) { }
};
The reason I want to do this is, I want to be able to instantiate a person class with something like:
Person person("The Name", Person::MALE);
But, because the enum is public this is also available:
Male::MALE
Male::FEMALE
Male::BOTH
which doesn't make any sense anymore. How can I prevent the derived class to be able to access those enum values, but make it available for public from the base class?
If you insist on keeping the enum within the base class, you can place the enum in a protected section.
class Person {
protected:
enum Gender { MALE, FEMALE, BOTH };
Person(std::string name, Gender gender)
: _name(name)
{
switch (gender) { /* processing here */ }
}
std::string _name;
public:
virtual ~Person () {}
//...
};
A class that derives from Person publicly will still have access to the enum values, but users of the derived class will not.
class Male : public Person {
public:
Male (std::string name) : Person(name, MALE) {}
//...
};
Thus, a Male can use MALE, but users of Male will not see Male::MALE, Male::FEMALE, nor Male::BOTH, which was one of your original issues. As to your questions, you don't really want to deny the derived class access, since you want the derived class to be able to specify the Gender. And you should not really allow any direct users of Person. Instead, a user of Person picks one of the correct derived classes, which will then establish Gender properly.
class Female : public Person {
public:
Female (std::string name) : Person(name, FEMALE) {}
//...
};
class Transgender : public Person {
public:
Transgender (std::string name) : Person(name, BOTH) {}
//...
};
std::shared_ptr<Person> p = std::make_shared<Female>("Beth");
The comments in the OP suggest a rethinking of your design, and probably that is the best alternative.
Still, if you want to keep up with what you wrote in the answer, one possibility is to derive protectedly from your base class
class Person {
public:
enum { MALE, FEMALE, BOTH };
Person(std::string name, int gender)
: _name(name)
{
switch (gender) { /* processing here */ }
}
protected:
std::string _name;
};
class Male : protected Person
{ //^^^^^^^^^
public:
Male(std::string name)
: Person(name, 0) { }
void foo() { FEMALE; } // still ok, a public field derived protected'ly is accessible
};
int main()
{
Male male("Joe");
male.MALE; //error, cannot call the enum from outside the class
}
the problem seems to be a literate one, there is no problem with the code per se, but in viewing the code as a language reflecting common notions.
In this sense i would suggest the following answer:
have a factory (or factory method) where the enum is public only in that factory. In other words create a new factory Human and have all base and derived classes using Human enums. Then the base class can still be Person but Person does not have any enum MALE/FEMALE/etc.. only the Human factory does, and it is not a base class that is subclassed. This would result in code which can be read literaly like this:
Person person("The Name", Human::MALE);
You can also use Gender factory (instead of Human) like this (to be even more literate and separate the inter-dependencies):
Person person("The Name", Gender::MALE);
Note that a base class includes the lowest common denominator that all derived classes must share. So since the derived classes Male Female etc are not supposed to share the gender enum then it should not be part of the base class, but a class or construct in itself which is then used by Person classes and its derivatives.
Simple make the Person class abstract using a protected constructor:
class Person {
public:
enum Gender {
MALE,
FEMALE,
BOTH
};
protected:
// Protected constructor can only be called from subclasses.
Person(std::string name, Gender gender)
: _name(name)
{
switch (gender) { /* processing here */ }
}
protected:
std::string _name;
};
class Male : public Person {
public:
Male(std::string name)
: Person(name, MALE)
{
}
};
If the gender is anyway independent from the Person class, just move it out of the class:
enum Gender {
GenderMale,
GenderFemale,
GenderBoth
};
class Person //...
class Male // ...
You can also encapsulate the Gender into a own class:
class Gender {
public:
enum Type { Male, Female, Both };
Gender(Type type);
Gender(const Gender ©);
Gender& operator=(Gender &assign);
public:
bool operator==(const Gender &other) const;
// etc.
public:
std::string toString() const;
};
I am trying to do this:
class Parameter
{
public:
Parameter(){};
~Parameter(){};
};
class Address : public Parameter
{
public:
Address(uint16_t val) : value(val){};
Address(const Address& b) : value(b.value){};
~Address(){};
private:
uint16_t value;
};
class Constant : public Parameter
{
public:
Constant(int val) : value(val){};
Constant(const Constant& b) : value(b.value){};
~Constant(){};
private:
int value;
};
How can I add set and get methods for the parent class Parameter so that when I create a Constant or Address object, I can use the parent methods to set and get the variable value?
Not sure what you meant, but here is a try:
template <typename T>
class Parameter
{
public:
const T& getValue() { return value; }
protected:
T value;
};
class Address : public Parameter<uint16_t>
{
public:
Address() { value = 2154; }
// ...
}
class Name : public Parameter<std::string>
{
public:
Name() { value = "John Doe"; }
// ...
}
Later you can do:
Address address;
Name name;
cout << name.getValue() << " lives at house no " << address.getValue();
// outputs "John Doe lives at house no 2154".
You could implement it as a pure virtual function and over ride it in the below classes?