I'm having this issue with inheritance I just cannot wrap my head around. I have three classes, with a parental relationship between them. All of them has the function calcForces().
class Object {
public:
virtual void calcForces();
};
class Boat : public Object {
public:
virtual void calcForces();
};
class Sailboat : public Boat {
public:
void calcForces(Wind wind);
};
Now my problem is that I I have a object created as a Sailboat (and saved it in an Object-pointer), but when I call calcForces() I end up inside Boat::calcForces(), not Sailboat::calcForces(). What am I doing wrong?
Here is my call to the function:
(*this->object_ptr_arr[i]).calcForces(); //'object_ptr_arr' is of type 'Object**'
The declarations of the overrides must match. Your declaration for Sailboat::calcForces takes a different parameter (a Wind instance) and therefore is not an override.
As commented by #stefaanv and #skypjack you can avoid this issue by embracing the use of the override function specifier, which would've caught the error at compile time.
If you want an calcForces() method in your sailboat you should add it there.
At the moment you only have a calcForces(Wind wind) method in your sailboat (and the calcForces() that is inherited from Boat)
So when you are calling calcForces without a parameter it will end up in the inherited method. To fix this either add it in Sailboat like described above or call it with an variable of type Wind
Suggestion - boats and sailboats exist in an environment. The boat knows how it is affected by the environment.
class Environment
{
public:
Wind wind;
};
class Object {
public:
virtual void calcForces(Environment const&);
};
class Boat : public Object {
public:
virtual void calcForces(Environment const& env); // can ignore the wind
};
class Sailboat : public Boat {
public:
void calcForces(Environment const& env) override; // will use env.wind in calculation
};
Now you are able to modify the environment and ask all objects in the environment to calculate their forces. Whether they're boats, sailboats or dolphins.
Related
I'm writing a C++ library for optimization, and I've encountered a curious issue with contra-variant types.
So, I define a hierarchy of "functions", based on what information they can compute.
class Function {
public:
double value()=0;
}
class DifferentiableFunction : public Function {
public:
const double* gradient()=0;
}
class TwiceDifferentiableFunction : public DifferentiableFunction {
public:
const double* hessian()=0;
}
Which is all well and good, but now I want to define interfaces for the optimizers. For example, some optimizers require gradient information, or hessian information in order to optimize, and some don't. So the types of the optimizers are contravariant to the types of the functions.
class HessianOptimizer {
public:
set_function(TwiceDifferentiableFunction* f)=0;
}
class GradientOptimizer : public HessianOptimizer {
public:
set_function(DifferentiableFunction* f)=0;
}
class Optimizer: public GradientOptimizer {
public:
set_function(TwiceDifferentiableFunction* f)=0;
}
Which I suppose makes sense from a type theoretic perspective, but the thing that is weird about it is that usually when people want to extend code, they will inherit the already existing classes. So for example, if someone else was using this library, and they wanted to create a new type of optimizer that requires more information than the hessian, they might create a class like
class ThriceDifferentiableFunction: public TwiceDifferentiableFunction }
public:
const double* thirdderivative()=0;
}
But then to create the corresponding optimizer class, we would have to make HessianOptimizer extend ThirdOrderOptimizer. But the library user would have to modify the library to do so! So while we can add on the ThriceDifferentiableFunction without having to modify the library, it seems like the contravariant types lose this property. This seems to just be an artifact of the fact the classes declare their parent types rather than their children types.
But how are you supposed to deal with this? Is there any way to do it nicely?
Since they're just interfaces, you don't have to be afraid of multiple inheritance with them. Why not make the optimiser types siblings instead of descendants?
class OptimizerBase
{
// Common stuff goes here
};
class HessianOptimizer : virtual public OptimizerBase {
public:
virtual set_function(TwiceDifferentiableFunction* f)=0;
}
class GradientOptimizer : virtual public OptimizerBase {
public:
virtual set_function(DifferentiableFunction* f)=0;
}
class Optimizer : virtual public OptimizerBase {
public:
virtual set_function(TwiceDifferentiableFunction* f)=0;
}
// impl
class MyGradientOptimizer : virtual public GradientOptimizer, virtual public HessianOptimizer
{
// ...
};
I have a problem with interfaces and multiple inheritance. I hope to design my program such that one update call processes a variety of objects, with each behavioral 'building block' tucked away in a single function.
For example, I'd like to move a creature from point A to B in one place, regardless of whether it must perform pre/post move actions. But, my multiple inheritance scheme fails (below, with the bug rem'd), making me think I'd need to duplicate code somewhere.
Clearly I don't understand this well enough! (but I'm working hard to learn it)
Q1. Why can't IPhysics::Move 'see' Creature::Move(), in the CreatureAirborne class?
Q2. Am I completely missing the proper usage of interfaces and/or multiple inheritance? If so, any guidance is appreciated!
#include <deque>
#include <memory>
class IGameObject
{
public:
virtual ~IGameObject() {}
virtual void Update() = 0;
};
class IPhysics
{
public:
virtual ~IPhysics() {}
virtual void Move() = 0;
};
class IPhysicsFlight : public IPhysics
{
public:
virtual ~IPhysicsFlight() {}
virtual void Land() = 0;
virtual void TakeOff() = 0;
};
class Creature : public IGameObject, IPhysics
{
protected:
virtual void Move() {}
public:
Creature() {}
virtual ~Creature() {}
virtual void Update() {}
};
class CreatureAirborne : public Creature, IPhysicsFlight
{
private:
virtual void Land() {}
virtual void TakeOff() {}
public:
CreatureAirborne() {}
virtual ~CreatureAirborne() {}
virtual void Update();
};
void CreatureAirborne::Update()
{
TakeOff();
Creature::Move();
Land();
}
int main()
{
std::deque<std::shared_ptr<Creature>> creatures;
std::shared_ptr<Creature> cow(new Creature);
creatures.push_back(cow);
// The butterfly fails to compile with 'cannot instantiate; void IPhysics::Move(void) is abstract'
// std::shared_ptr<CreatureAirborne> butterfly(new CreatureAirborne);
// creatures.push_back(butterfly);
for (auto i : creatures)
{
i->Update();
}
}
It's somewhat had to follow your hierarchy, but it looks correct evaluation on the compiler's part.
You don't have virtual inheritance anywhere, so CreatureAirborne will have duplicated base classes from some point. You will have two instances of IPhysics. Move, that is abstract from there is implemented on the Creature branch but remains abstract on IPhysicsFlight.
You can cure the situation by using virtual inheritance somewhere, or by implementing Move in descendant (say just calling the parent version where it exists).
I would look at things little differently
class CreatureAirborne : public IPhysicsFlight,Creature
While the code runs
new CreatureAirborne ()
The compiler will try to build IPhysicsFlight base class and Creature base class and the fact that IPhysics is a base class to both doesn't play any role rather than confusing.As far as compiler is concerned IPhysicsFlight is abstract and CreatureAirborne did not implement Move
The diamond issue will actually come into play when you do a
(new CreatureAirborne ())->Move()
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.
There probably is a fairly simple and straight-forward answer for this, but for some reason I can't see it.
I need to restrict calling methods from a class only to some methods implemented by derived classes of some interface.
Say I have
class A{
public:
static void foo();
};
class myInterface{
public:
virtual void onlyCallFooFromHere() = 0;
}
class myImplementation : public myInterface{
public:
virtual void onlyCallFooFromHere()
{
A::foo(); //this should work
}
void otherFoo()
{
A::foo(); //i want to get a compilation error here
}
}
So I should be able to call A::foo only from the method onlyCallFooFromHere()
Is there a way to achieve this? I'm open to any suggestions, including changing the class design.
EDIT:
So... I feel there's a need to further explain the issue. I have a utility class which interacts with a database (mainly updates records) - class A.
In my interface (which represents a basic database objects) I have the virtual function updateRecord() from which I call methods from the db utility class. I want to enforce updating the database only in the updateRecord() function of all extending classes and nowhere else. I don't believe this to be a bad design choice, even if not possible. However, if indeed not possible, I would appreciate a different solution.
Change the class design - what you want is impossible.
I am unsure of what you are trying to achieve with so little details and I am unable to comment further.
[Disclaimer: this solution will stop Murphy, not Macchiavelli.]
How about:
class DatabaseQueryInterface {
public:
~virtual DatabseQueryInterface() = 0;
virtual Query compileQuery() const = 0; // or whatever
virtual ResultSet runQuery(const Query&) const = 0; // etc
};
class DatabaseUpdateInterface : public DatabaseQueryInterface {
public:
virtual Update compileUpdate() const = 0; // whatever
};
class DatabaseObject {
public:
virtual ~DatabaseObject() = 0;
protected:
virtual void queryRecord(const DatabaseQueryInterface& interface) = 0;
virtual void updateRecord(const DatabaseUpdateInterface& interface) = 0;
};
class SomeConcreteDatabaseObject : public DatabaseObject {
protected:
virtual void updateRecord(const DatabaseUpdateInterface& interface) {
// gets to use interface->compileUpdate()
}
virtual void queryRecord(const DatabaseQueryInterface& interface) {
// only gets query methods, no updates
}
};
So the basic idea is that your DatabaseObject base class squirrels away a private Query object and a private Update object and when it comes time to call the protected members of the subclass it hands off the Update interface to the updateRecord() method, and the Query interface to the queryRecord() method.
That way the natural thing for the subclasses is to use the object they are passed to talk to the database. Of course they can always resort to dirty tricks to store away a passed-in Update object and try to use it later from a query method, but frankly if they go to such lengths, they're on their own.
You could split your project into different TUs:
// A.h
class A
{
public:
static void foo();
};
// My.h
class myInterface
{
public:
virtual void onlyCallFooFromHere() = 0;
}
class myImplementation : public myInterface
{
public:
virtual void onlyCallFooFromHere();
void otherFoo();
};
// My-with-A.cpp
#include "My.h"
#include "A.h"
void myImplementation::onlyCallFooFromHere() { /* use A */ }
// My-without-A.cpp
#include "My.h"
void myImplementation::otherFoo() { /* no A here */ }
You probably know this, but with inheritance, you can have public, protected, and private member access.
If a member is private in the base class, the derived cannot access it, while if that same member is protected, then the derived class can access it (while it still isn't public, so you're maintaining encapsulation).
There's no way to stop specific functions from being able to see whats available in their scope though (which is what you're asking), but you can design your base class so that the derived classes can only access specific elements of it.
This could be useful because class B could inherit from class A as protected (thus getting its protected members) while class C could inherit from the same class A as public (thus not getting access to its protected members). This will let you get some form of call availability difference at least -- between classes though, not between functions in the same class.
This could work.
class myInterface;
class A {
private:
friend class myInterface;
static void foo();
};
class myInterface {
public:
virtual void onlyCallFooFromHere() {callFoo();}
protected:
void callFoo() {A::foo();}
};
Though at this point I think I'd just make A::foo a static of myInterface. The concerns aren't really separate anymore.
class myInterface {
protected:
static void foo();
};
Is there a reason foo is in A?
I have the following abstract base class, SettingsInterface, that I use as an interface:
class SettingsInterface
{
public:
virtual void Refresh() = 0;
virtual void Update() = 0;
virtual void OnConnect() = 0;
virtual void OnDisconnect() = 0;
};
I'm trying to implement this interface in my class below, which inherits from TFrame. TFrame inherits from another class that also has a virtual method called Update.
class DebugSettingsFrame : public TFrame, public SettingsInterface
{
//a bunch of IDE-managed components - left out for brevity
public:
virtual void Refresh();
virtual void Update();
virtual void OnConnect();
virtual void OnDisconnect();
};
When I compile this, I get the error virtual function DebugSettingsFrame::Update() conflicts with base class 'TWinControl'.
I'm stomped on this. How can I resolve this without changing my interface's method definition, Update, to something else?
Edit - Follow-up:
So C++ doesn't have a construct similar to C# where you can explicitly implement interface methods that have the same definition?
Thanks!
Try something like (from the code I can't say exactly):
DebugSettingsFrame::TFrame::Update();
:: is the scope resolution operator. You should be able to specify precisely which version of the function you are calling.
However, note that this is a symptom of a design that may be getting too complex.