C++: Polymorphism - c++

I want to start by showing some code and explain my problem later.
Base class:
class swcObject :
public swcRectangle
{
public:
bool visible;
};
Sub-base class[optional, abstract]:
class swcText
{
public:
std::string text;
protected:
virtual void attachedToParent() = 0;
};
Derived classes:
class swcLabel :
public swcObject,
public swcText
{
public:
int text_align;
private:
void attachedToParent();
};
...
class swcComboBox :
virtual protected swcObject
{
public:
void setPosition(int x, int y);
private:
swcLabel label;
};
Now I have this class w/c has a member object of type std::vector<swcObject>.
class swcWindow :
private swcObject
{
public:
void addObject(const swcObject &object);
private:
std::vector<swcObject> objects;
};
I came into this few problems w/c I haven't encountered before and Google seems don't have a relevant problem like mine.
My specific problems are:
Relevant code:
swcWindow window;
swcComboBox cbox;
window.addObject(cbox);
Error:
'swcObject' is an inaccessible base of 'swcComboBox'
Desire:
I do not want to access swcComboBox::swcObject members on public scope like this cbox.x = 0;, but instead cbox.setPosition(0, 0); because there will be always an adjusting of some member elements whenever the swcComboBox had changed its location.
Relevant code:
swcWindow window;
swcLabel label;
window.addObject(label);
Error:
In this case, label have a base classes of swcText and swcObject. After adding the label to one of member of window.objects (is of type std::vector), swcText properties are gone, like the text property.
Desire:
I want to create a temporary objects and initialize its property in a init() method outside of those classes and copy it using swcWindow::addObject(). Is this possible without a cast? I think this one would do but its awful(?), and I didn't try it yet if this is working:
void addObject(const swcObject &object, SWC_TYPES type)
{
switch (type)
{
case LABEL:
//do casting?
...
}
}
Please recommend any other way how can I achieve those kind of implementation with the same functionalities.

vector store elements by value, as if you passed your ComboBox to a procedure which takes a swcObject by value, not by reference. This leads to cut of object to its base class, which is prohibited if you use protected inheritance.
You shouldn't store polymorphic objects in vector, just as you shouldn't pass them by value. You can try storing references or (smart) pointers in vector - that should solve your problems.

Related

C++: Extend member type in derived class

I'd welcome some help with C++ inheritance to get a better grasp of the concept.
Is it possible to "extend" member types when creating a derived class? I think my problem can be best demonstrated by a simple example, where I'd like to extend the class VehicleData with a new double variable:
class VehicleData {
int yearOfManufacture;
//Different routines, for example Serialize(), etc., warranting to create a class for just a bunch of variables
};
class BicycleData:VehicleData {
double frameHeight; //new property that only applies to bicycles
};
//Now I create the actual classes that use the types above
class Vehicle {
VehicleData data;
void PrintData(); //a function that works on basic vehicle data
};
class Bicycle:Vehicle {
BicycleData data; //should copy VehicleData when creating an instance of this class
};
The problem with this approach is that when I code the above and create a Bicycle instance, its BicycleData member hides the already existing VehicleData member.
Is there a way to extend the base class, i.e. simply add a new double variable (to store frame height in this example), and keep the already existing (year of manufacture) data?
As far as I can tell, there is no clean way to do exactly what you want with inheritance alone.
You could create a template out of your base class:
template <typename Data>
class BaseVehicle
{
Data data;
// etc.
};
class Vehicle : BaseVehicle<VehicleData>
{
// etc.
};
class Bicycle : BaseVehicle<BicycleData>
{
// etc.
};
Then the Vehicle and Bicycle classes would contain data field of VehicleData and BicycleData types respectively.
Since in your example Bicycle inherits from Vehicle privately (i.e. there is no support for using Bicycle polymorphically via pointer/reference to Vehicle), this would effectively be identical to what you want to achieve.
If you do want dynamic polymorphism, you should create a separate, preferably abstract, class, defining the interface for your vehicles, e.g.:
class VehicleInterface
{
public:
// Some pure virtual interface methods
virtual void moveTo(const Vector2 position) = 0;
virtual ~VehicleInterface() = default;
};
And then you can have your concrete vehicles inherit and implement this interface:
class Vehicle : BaseVehicle<VehicleData>, public VehicleInterface
{
public:
virtual void moveTo(const Vector2 position) override
{
// implementation for Vehicle
}
};
class Bicycle : BaseVehicle<BicycleData>, public VehicleInterface
{
public:
virtual void moveTo(const Vector2 position) override
{
// implementation for Bicycle
}
};
Then any function, which would like to work with vehicles polymorphically, can just accept a reference or a pointer to VehicleInterface:
void driveToWork(VehicleInterface* vehicle)
{
vehicle->moveTo(getWorkPosition());
// etc.
}
Short answer; Not in the way that you're aiming for, but you can achieve something similar.
Rather than have an instance declared as you have, if you make data a pointer. You can then have BicycleData inherit VehicleData and then just replace data with the new instance in the constructor of the Bicycle.
ie
class Vehicle {
void PrintData();
protected:
void replaceData(std::shared_ptr<VehicleData> d) {
data = d;
}
std::shared_ptr<VehicleData> getData() {
return data;
}
template<class T>
std::shared_ptr<T> getDataAs() {
return std::dynamic_pointer_cast<T>(data);
}
private:
std::shared_ptr<VehicleData> data;
};
class Bicycle:Vehicle {
Bicycle(){replaceData(std::make_shared<BicycleData>());}
std::shared_ptr<BicycleData> getData() {
return getDataAs<BicycleData>();
}
};

Parent class referencing child variable

I have several similar classes inheriting from the same Base-Class/Interface (Base class 1), and they share a couple similar functions, but then also have their own distinct functions. They all also have their own member variables of different classes, and each of those inherits from the same Base-Class/Interface (Base class 2). Is it possible to define a variable in Base class 1, of type Base class 2, then in the actual implementation of classes using Base class 1, have the variable of type Base class 2 be its proper type. Kinda hard to explain, so simplified example below.
//Base-Class 1
class Shape
{
public Shape() {}
ShapeExtra m_var;
//The common functions
public GetVar(){ return m_var; }
}
class Circle : Shape
{
public Circle() { m_var = new CircleExtra(); }
public void CircleFunc()
{
m_var.CircleExtraFunc();
}
}
class Triangle : Shape
{
public Triangle() { m_var = new TriangleExtra(); }
public void TriangleFunc()
{
m_var.TriangleExtraFunc();
}
}
.
.
.
//Base_Class 2
class ShapeExtra
{
public ShapeExtra() {}
}
class CircleExtra : ExtraClass
{
public CircleExtra() {}
void CircleExtraFunc() {//Do stuff}
}
class TriangleExtra : ExtraClass
{
public TriangleExtra() {}
void TriangleExtra() {//Do stuff}
}
.
.
.
So, I need the m_var in the child classes to be kept it as its own unique version. Because right now (w/o the extra CircleExtra m_var;), the GetVar() works, but in CircleFunc, m_var is still type of ShapeExtra, and thus doesn't know that CircleExtraFunc exists. I could cast m_var each time I wanted to do that, but that is repetitive and not worth it in my real-world case. Is there a way to utilize the functions in unique classes based off of ShapeExtra, while keeping the GetVar() function in Shape?
Please ask questions if there is anything I left out.
Simply with inheritance and without using pointers it is not possible, as C++ is a statically-and-strictly-typed language.
You can inherit both the variable and the function, but you'll need to cast function return value.
You can also override the function to make it return the concrete type, but then you have to cast the variable inside the function.
You can also declare the same var with the concrete class in subclasses, but then you just hide the variable in the superclass and inherit nothing.
I'd rather go for a solution using templates. Make the type of the variable a template type and extend the template using a concrete type in subclasses. It'll work perfectly.
It's been a long time since I last programmed in C++ and I beg your pardon if there are errors in the following example. I'm sure you can easily make it work.
template <class S>
class Shape {
S m_var;
//......
public:
S var () {
return m_var;
}
//.......
}
class Circle: Shape <CircleExtra> {
// var method returns CircleExtra
//......
}
Edit:
Regarding some comment, to allow virtual invocation of the method, it is possible to use correlated return types. Something like the following example.
class Shape {
public:
virtual ShapeExtra *var () = 0;
}
template <typename SE>
class ConcreteShape: Shape {
public:
virtual SE *var() {
return &m_var;
}
// Constructor, etc.
private:
SE m_var;
}
Or some variation. Now concrete shapes can benefit from extending the template, as long as SE * is correlated with ShapeExtra * (the type parameter extends ShapeExtra). And you can vall the method transparently through Shape interface.
Using pointers, this is totally possible.
Using your example, you could do something like this:
#include <iostream>
#include <memory>
using namespace std;
//Extras
class ShapeExtra
{
public:
ShapeExtra() {}
void ShapeFunc() { std::cout << "Shape"; }
virtual ~ShapeExtra() = default; //Important!
};
class Shape
{
public:
std::unique_ptr<ShapeExtra> m_var;
//require a pointer on construction
//make sure to document, that Shape class takes ownership and handles deletion
Shape(ShapeExtra* p):m_var(p){}
//The common functions
ShapeExtra& GetVar(){ return *m_var; }
void ShapeFunc() {m_var->ShapeFunc();}
};
class CircleExtra : public ShapeExtra
{
public:
void CircleExtraFunc() {std::cout << "Circle";}
};
class Circle : public Shape
{
CircleExtra* m_var;
public:
Circle() : Shape(new CircleExtra()) {
m_var = static_cast<CircleExtra*>(Shape::m_var.get());
}
void CircleFunc()
{
m_var->CircleExtraFunc();
}
};
int main() {
Circle c;
//use the ShapeExtra Object
c.GetVar().ShapeFunc();
//call via forwarded function
c.ShapeFunc();
//call the circleExtra Function
c.CircleFunc();
return 0;
}
Test it on ideone
Note the use of pointers and a virtual destructor:
By using a virtual destructor in the ShapeExtra base class, you make it possible to destruct an object of any derived class, using a ShapeExtra*. This is important, because
by using a std::unique_ptr<ShapeExtra> instead of a plain C-pointer, we make sure that the object is properly deleted on destruction of Shape.
It is probably a good idea to document this behaviour, i.e. that Shape takes the ownership of the ShapeExtra*. Which especially means, that we do not delete CirleExtra* in the Circle destructor
I decided here to require the ShapeExtra* on construction, but its also possible to just use std::unique_ptr::reset() later and check for nullptr on dereferencing Shape::m_var
Construction order is this: On calling the constructor of Circle, we first create a new CircleExtra which we pass to Shape before finally the constructor of Circle is executed.
Destruction order is Circle first (was created last), then Shape which also destructs the ShapeExtra for us, including (via virtual function) the CircleExtra
I would recommend the following approach:
class ShapeExtra
{
public:
virtual ~ShapeExtra() { }
virtual void SomeCommonShapeFunc() { std::cout << "Shape"; }
};
class Shape
{
public:
virtual ShapeExtra &GetVar() = 0; // Accessor function.
};
Note that the class Shape does not have any data members at all. After that for each derived class you need:
class CircleExtra : public ShapeExtra
{
public:
void SomeCommonShapeFunc() { std::cout << "Circle"; }
};
class Circle : public Shape
{
CircleExtra m_var; // Data member with circle specific class.
public:
virtual ShapeExtra &GetVar() { return m_var; }
};
Implementation of virtual method in Circle will return reference to the base class ShapeExtra. This will allow using this extra in the base class.
Note that pointers and templates are not used at all. This simplifies the overall design.

Inheritance between two classes in c++ using the same data members and functions

I'm new to C++ programming and I want to create two classes that have the exact same data members and functions. Is it possible to create two inherited classes that have the same data members/functions instead of making several duplicate methods for each class. I'm making a c++ game based on zork and I want to create two items, weapons and fruits. Both will take in a name as a string and a value as a double. Do I create the header file as below:
#ifndef ITEM_H_
#define ITEM_H_
#include <map>
#include <string>
#include <iostream>
using namespace std;
class Item {
private:
string description;
string longDescription;
float value;
public:
Item (string description, float inValue);
Item (string description);
string getShortDescription();
string getLongDescription();
float getValue();
void setValue(float value);
};
class Weapon:: public Item{
};
class Fruit:: public Item {
};
#endif /*ITEM_H_*/
How would I no go about creating the methods without duplicating them?
Do nothing for now. Both Weapon and Fruit are Items and contain all the members and methods that Item does.
Sooner or later, you'll want to specialize behaviour of child classes and the implementation of the method in the base class won't do it (if it's sensible to have an implementation in the first place). This is where polymorphism comes in. You'll make the method in the base class virtual and override it in the derived class:
class Item {
public:
virtual void Use() = 0; // pure virtual method
};
class Weapon : public Item {
public:
virtual void Use() override
{
Fire();
}
private:
void Fire() { /* do something */ }
};
Now when you have a reference or a pointer to the base class and you call Use on it, it'll dispatch to the corresponding method in the derived class.
EDIT: There's no way around "duplicating" constructors. Each class needs at least one if it is ever to be instantiated. Since you declared Item (string description, float inValue); you need to define it as a member of Item, too:
Item (string description, float inValue)
: description(description) // <-- avoid duplicating names of members in parameter list,
, value(inValue) // it does the right thing, but hurts readability
{ /* body empty */ }
If you need to call the constructor of the derived class with same parameters, you need to define another constructor and forward the arguments to the constructor of base class:
Weapon::Weapon(string desc, float val)
: Item(desc, val) { }
In C++11, there's a shortcut - you can inherit constructors and the compiler will generate these forwarding constructors for you:
class Weapon : public Item {
using Item::Item;
};
There's (unfortunately, perhaps) no way to specify which constructors you want to inherit. It's all or nothing.
Hope that helps.
you need to call constructor of parent class to assign value to description; and longDescription; like
class Weapon:: public Item{
Weapon(string description, float inValue):Item(description,inValue){}
Weapon(string description):Item(description){}
};

Multiple public/private keyword in class definition

I have seen multiple public and private keywords in a class definition, like the example below:
class myClass
{
public:
void func1(){}
public:
void func2(){}
private:
int x;
int y;
private:
int z;
int baz;
};
What is the practical use of this (if any)? Is there any situation in which this could be useful?
Is there any situation in which this could be useful?
I can think of a situation where it would be very problematic otherwise:
class myClass
{
public:
void func1(){}
public:
void func2(){}
COORDINATES; // <-- Note the macro here!
private:
int z;
int baz;
};
which, after the expansion of the COORDINATES macro, becomes:
class myClass
{
public:
void func1(){}
public:
void func2(){}
private:
int x;
int y;
private:
int z;
int baz;
};
If multiple private / public keywords weren't allowed, it would be very painful to do it. Although using macros isn't good practice; neither is introducing access modifiers silently for all the members appearing after the macro. Nevertheless, it could be useful for RAD tools generating C++ source code.
I can only guess why you see that in human written classes. My guess is that it is poor coding; the writer probably wanted to express that a chunk of data belongs together and / or wanted to be able to move up and down those chunks within the class definition, together with the corresponding access modifier (private/protected/public).
I'll go one step farther from my comment for this answer, with a snippet of code.
class myClass {
// initializers etc
public:
myClass();
~myClass();
// signal processing
public:
void modifyClass();
private:
float signalValue;
// other class responsibilities
public:
void doWork();
private:
void workHelper();
};
and so on. I wouldn't say this is a solid DESIGN for the class, but it's a good way to show the different capabilities of a class.
Another use is when you want to have a specific destruction order. Lets consider two cases:
Bad case
// Auxiliary class
Class StorageCleaner {
public:
StorageCleaner(ExternalStorage* storage) : storage_(storage);
~StorageCleaner() { storage_->DeleteEverything(); }
private:
ExternalStorage* const storage_; // Not owned
}
// Class with bad declaration order
Class ExternalStorageWrapper {
public:
ExternalStorageWrapper(ExternalStorage* storage) : cleaner_(storage) {
pointer_to_storage_.reset(storage);
}
const StorageCleaner cleaner_;
private:
std::unique_ptr<ExternalStorage> pointer_to_storage_;
// Other data which should be private
int other_int;
string other_string;
....
};
What happens when existing ExternalStorageWrapper object goes out of scope?
The ExternalStorageWrapper destructor will first
destroy other data
Then it will destroy external storage pointed by pointer_to_external_storage_ (because fields are destroyed in reversed declaration order).
Then it will attempt to destroy cleaner_
But cleaner inside its own destructor attempts to manipulate external storage, which has already been destroyed!
Good case
// Class StorageCleaner same as before
...
// Class with better declaration order
Class ExternalStorageWrapper {
private:
std::unique_ptr<ExternalStorage> pointer_to_storage_;
public:
ExternalStorageWrapper(ExternalStorage* storage) : cleaner_(storage) {
pointer_to_storage_.reset(storage);
}
const StorageCleaner cleaner_;
private:
// Other data which should be private
int other_int;
string other_string;
....
};
What happens in this case when existing ExternalStorageWrapper object goes out of scope?
The ExternalStorageWrapper destructor will first destroy other data.
Then it will attempt to destroy cleaner_. Cleaner will DeleteEverything() from storage using storage_ pointer to still existing storage.
Finally, storage gets destroyed through pointer_to_storage_.
I actually had to debug such problem in a company, so although rare, this peculiar case is possible to occur.
One use case I encounter is for the clarity. As shown in the example below, class1 inherits base class which contains a pure virtual function that class1 needs to implement. To indicate that method1 in class1 is coming from some other class class1 inherits from (e.g. base) instead of class1's own function, we use another public to make this point clear:
class base {
public:
virtual void method1() = 0;
}
class class1: base {
public:
myOwnMethod1();
myOwnMethod2();
public: /* base interface */
method1();
Just finished reading those examples. Hopefully this one could contribute on how useful multiple keyword definition is.
We don't quite need to assume much since this is my current problem as of now but consume the following:
class IOHandler {
public:
enum COLOR_DEFINITIONS : unsigned char
{
BLACK,
DARK_ER_BLUE,
DARK_GREEN,
DARK_SKY_BLUE,
DARK_RED,
DARK_PINK,
DARK_YELLOW,
DARK_WHITE,
DARK_GREY,
DARK_BLUE,
BRIGHT_GREEN,
BRIGHT_SKY_BLUE,
BRIGHT_RED,
BRIGHT_PINK,
BRIGHT_YELLOW,
BRIGHT_WHITE
};
template <typename dtEX>
void showOutputEx(dtEX literalOutput, _COLOR_OUTPUT textColorSet = {COLOR_DEFINITIONS::BRIGHT_WHITE , COLOR_DEFINITIONS::BRIGHT_YELLOW}, bool appendOutputType = true, OUTPUT_TYPE levelOutput = OUTPUT_TYPE::OUTPUT_NORMAL, EMBRACE_TYPE embraceOutputType = EMBRACE_TYPE::EMBRACE_OUTPUT_LEVEL, ...);
// ! ^^^^^^^^^^^^^^ Doesn't detect the struct being referenced at which is at below.
private:
typedef struct colorProps // This is the struct that the public function where trying to get referenced at but failed to do so.
{
unsigned char C_BG = 0,
C_FG = 0;
} _COLOR_OUTPUT;
};
The error code.
identifier "_COLOR_OUTPUT" is undefined.
At this point, my intelliSense keep complaining that _COLOR_OUTPUT is undefined within public class scope.
The most probable solution is to put the struct inside public scope instead of private scope.
But I don't want to.
The reason this happens was due to the compiler reads the file from top to bottom. Anything that is declared
that requires reference should be on top and that should resolve the issue. Since I don't want to make things messed up by putting all private class functions and variables
on top. I should just declare another specifier on the top so that any public function requiring some reference might see it ahead.
So the solution is the following: (Is to move all referrable variables and struct on top of the class so that any private and public function argument reference is being recognized.)
class IOHandler {
// Private Class Scope for Variables and Structure
private:
typedef struct colorProps // This is the struct we move at the top for recognizing references.
{
unsigned char C_BG = 0,
C_FG = 0;
} _COLOR_OUTPUT;
public:
enum COLOR_DEFINITIONS : unsigned char
{
BLACK,
DARK_ER_BLUE,
DARK_GREEN,
DARK_SKY_BLUE,
DARK_RED,
DARK_PINK,
DARK_YELLOW,
DARK_WHITE,
DARK_GREY,
DARK_BLUE,
BRIGHT_GREEN,
BRIGHT_SKY_BLUE,
BRIGHT_RED,
BRIGHT_PINK,
BRIGHT_YELLOW,
BRIGHT_WHITE
};
template <typename dtEX>
void showOutputEx(dtEX literalOutput, _COLOR_OUTPUT textColorSet = {COLOR_DEFINITIONS::BRIGHT_WHITE , COLOR_DEFINITIONS::BRIGHT_YELLOW}, bool appendOutputType = true, OUTPUT_TYPE levelOutput = OUTPUT_TYPE::OUTPUT_NORMAL, EMBRACE_TYPE embraceOutputType = EMBRACE_TYPE::EMBRACE_OUTPUT_LEVEL, ...);
// ! ^^^^^^^^^^^^^^ Now recognizable reference.
private:
... // Any other functions, excerpt.
};

C++ Creating Child Class from a Parent Class that's already been initialised

I have a class "Player". Its members are simple strings and ints and I've got Getters and Setters for each of these...basic stuff: (there's a load of members so I've just given 3 to shrink the code):
PLAYER.H
class Player
{
private:
string Name;
string Role;
int FFDefence;
......etc
public:
//constructor function
Player(
string Name = "Not Stated",
string vRole = "Not Stated",
int vFFDefence = 0,
......etc
)
//Getter Functions
string GetName() const;
string GetRole() const;
int GetFFDefence() const;
.....etc
//Setter Functions
void SetName (string x);
void SetRole(string x);
void SetFFDefence(int x);
......etc
};
PLAYER.CPP
Player::Player( string vName,
string vRole,
int vFFDefence,
......etc
{
Name = vName;
Role = vRole;
FFDefence = vFFDefence,
......etc
}
//getter functions
string Player::GetName() const {return Name; };
string Player::GetRole() const {return Role; };
int Player::GetFFDefence() const {return FFDefence; };
.....etc
//Setter Functions
void Player::SetName(string x) { Name = x ; };
void Player::SetRole(string x) { Role = x ; };
void Player::SetFFDefence(int x) { FFDefence = x ; };
......etc
So yeah - pretty bog standard......now I have a second class where one of the member functions is a Player Class itself.
BATTER.H
class Batter
{
private:
Player ID;
int Touch;
....etc
public:
Batter(Player vID, int vTouch = 0....etc);
//Getter Functions
string GetRole() const;
int GetFFDefence() const;
int GetBFDefence() const;....and so on.
OK - that's the code out of the way!!!!
So I've got it doing everything I want in terms of passing variables in and out....so I can create
Player Dave ("Dave", "Opener", 98, ....etc)
then later on (when I need it) create
Batter OnStrike (Dave, 10, .....etc)
All gravy....OK so I've started looking into inheritance and realized this is what I should be doing....back converting not a problem (did this with arrays and vectors the other day)...
Here's my problem:
With what I've got now, I can create "Player Dave" and then pass him into the subclass of Batter whenever I need to. How do I do the same with traditional inheritance? How do I take a specific instance (already created) of Player and use that as the parent for a specific instance of the child class Batter? As far as I can deduce at the moment, you need to create both at the same time.
Just initialize your base object with the object provided:
class Player
{
Player(Player const&); // copy constructor (might be implicitly generated)
...
};
class Batter:
public Player
{
Batter(Player const& p, other arguments):
Player(p),
...
{
...
}
};
On the other hand, there's the question whether inheritance of Batter from Player is the right tool in your case. The fact that you pass a Player object to construction hints at the fact that a Player may become a batter, and maybe later also stop being a batter. That is, Batter is actually a role which the player may temporarily have. Therefore it may be a better idea to separate the Player object from the role, by having a separate Role hierarchy where Batter and Pitcher derive from Role, and Player has a method which returns the current role, and another which can assign another role to the player.
The idea with polymorphism is that if you have some class:
class Batter : public Player
Then every batter is also a player. So, for example, if you had a batter called dave, you'd be able to use dave wherever a Player was expected. You could for example:
int FunctionThatDoesSomething(Player &p, string some_parameter, ...);
...
FunctionThatDoesSomething(dave, "foo", ...);
Be careful to avoid slicing, which is when you accidentally make a base class copy of a subclass (this does not preserve subclass specific state. If you need to pass dave around, make sure you only refer to dave, don't copy dave. dave doesn't like to be copied.)
How exactly you build your players and batters is up to you. For example, your might have constructors with these signatures:
Player::Player(string name, string role, int vFFDefense);
Batter::Batter(Player &p, int vTouch, int moreStats);
Under some circumstances this might be convenient, but it's not particularly efficient because you have to create and copy the base class (not that efficiency is a big deal for small classes like this, but there's no point in trying to do things the dumb way). You would be better off making a constructor that takes everything it needs, and uses subobject initialization:
Batter::Batter(string name, string role, int vFFDefense, int moreBaseStats, int vTouch, int moreStats) : Player(name, role, vFFDefense, moreBaseStats)
{
...
But your implementation is ultimately up to you.
You are doing aggregation here, not inheritance. A Batter has a player. Inheritance would be a batter is a player.
Your design is good, you don't want to do inheritance for this.
While it's okay to say a Batter is always a Player from a conceptual point of view in this case, when you are dealing with a Batter, much of what player describes is irrelevant and when dealing with them as a player, they may not be batting.
Baseball is a bit foreign to me, but if you went down the inheritance route, you'd have descendants of player for each role in the team and get in a right mess when your pitcher came out to bat.
A classic illustration of the inheritance route.
Is
Animal -> Fliers -> Bird -> Merlin
-> Runners -> Rodent -> Gerbil
Where do you put Bat and Ostrich?
You are left with saying a Bat is a bird, inventing a new class FlyingRodent, or Rodent having two parents...
All of which will lead to a confusing bug fest.
View all unconscious reaches for the inheritance hammer with extreme suspicion.
It really depends how you actually want your code factored.
Will a given Player ever become anything other than a Batter? If they can, then it is probably best to use aggregation (in a similar way to how you do now).
If you are aggregating then maybe use another class to hold the data. You could have a PlayerInfo class or struct and aggregate that:
struct PlayerInfo
{
string role_;
int ff_defence_;
...
};
class Player
{
public:
Player(PlayerInfo const& info)
: info_(info)
{}
virtual ~Player() = 0;
virtual void doSomething();
PlayerInfo const& getPlayerInfo() const { return info_; }
private:
PlayerInfo info_;
};
class Batter : public Player
{
public:
Batter(PlayerInfo const& info)
: Player(info)
{}
virtual void doSomething();
};
If you actually want the inheritance then other answers here tell you what you need to do - construct an instance of Batter and pass on the constructor arguments to a constructor of the class you derive from (e.g. Batter) to initialize it.
Think carefully about what are you trying to express in your code.
The reason you would want to have Batter derived from Player is if you need virtual functions in Player that are implemented in Batter and do something different depending upon whether or not it is a Player or a Batter.
As an aside, its best to keep base classes abstract if possible, so Player would never be instantiated directly and would always need to be derived. I'd recommend reading Scott Meyers 'More Effective C++' to understand why this is. There's a section in there devoted to that. In fact some of the finer points of inheritance and OO design in general are nicely explained.
What you may actually want is something slightly different depending upon where you anticipate your model to change, and additionally where you you need it to have the dynamic behaviour possible through the use of virtual functions?
You could have a Player class that has all your player specific details. Then you could have a PlayerBehaviour class that implements what the player does:
class Player;
class PlayerBehaviour
{
public:
virtual ~PlayerBehaviour() = 0;
virtual void doSomething(Player* player) = 0;
};
inline PlayerBehaviour::~PlayerBehaviour() {}
class BatterBehaviour : public PlayerBehaviour
{
public:
virtual void doSomething(Player* player) {
if (player->isAngry()) {
throwBatOnFloor();
}
}
void throwBatOnFloor();
};
class Player {
public:
Player(...stuff...);
void doSomething() {
if (behaviour_.get()) {
behaviour_->doSomething(this);
}
}
private:
auto_ptr<PlayerBehaviour> behaviour_;
// Due to the auto_ptr, the default copy and assignment operators are
// dangerous. You could use a smart pointer or implement
// these by having a clone() function in the behaviour class.
// Therefore copy/assign are private to prevent accidental misuse.
Player(Player const&);
Player& operator=(Player const&);
};
So, inheriting Batter from Player models the situation as a Batter is-a Player.
Having a Behaviour models the situation as a Player has-a Behaviour such as a Batter.
Stop using the "parent" and "child" terminology, think of "base" classes and "derived" classes ... that's what everyone else calls them. "Parent" and "child" can be used in too many other ways (e.g. an object that owns another one) so it's confusing terminology if you're talking about an inheritance relationship.
The derived class contains an entire instance of the base type inside itself. When the derived constructor starts executing the first thing it does is construct all its bases, which it does by calling their constructors. So the derived class can control how the base is constructed by passing it the right arguments:
class Base {
public:
Base(std::string nm) : name(nm) { }
protected:
std::string name;
};
class Derived : public Base {
public:
// construct my base by passing name to it
Derived(std::string name, int ii) : Base(name), i(ii) { }
private:
int i;
};
Derived d("Dave Derived", 1);
This creates both the Base and Derived objects at the same time (one inside the other) which is probably what you want.
If do have an existing Base object and you want the base part of the derived object to be the same as that other one then you can pass it an object to copy:
class Base {
public:
Base(std::string nm) : name(nm) { }
protected:
std::string name;
};
class Derived : public Base {
public:
// construct my base by passing name to it
Derived(std::string name, int ii) : Base(name), i(ii) { }
// construct my base by passing another Base to it:
Derived(const Base& b, int ii) : Base(b), i(ii) { }
private:
int i;
};
Base b("Barry Base");
Derived d(b, 2);
This doesn't put the existing Base object, b, inside the Derived one, instead it makes the base object a copy of the object b, by calling the Base copy constructor, so now there are two Base objects, the original b and the one inside d. This is closer to your original code, where the Batter contains a Player member, but now it's a base class not a member.
If you do want to use inheritance, the first form is probably more appropriate, where you pass arguments to the derived class and it uses those arguments to create the base.