recently i have read some about pure virtual function concept in c++ and i wonder, given following code:
class First
{
public:
virtual void init() = 0;
protected:
bool initialized;
};
class Second : public First
{
public:
void init() { ((*someting*) ? (initialized=true) : (initialized=false));
};
if creator of First class wanted to ensure the implementation of init() MUST set initialized variable either true or false how can they do that? Is there an option to enforce implementation of pure virtual function to set any variable inherited from base class?
You can make init protected and have it return bool.
Then have a new initialize method which is public and also sets the initialized member.
Since init now has a return value, it must be set by anyone who implements derived classes.
class First
{
public:
void initialize() { initialized = init(); }
protected:
virtual bool init() = 0;
bool initialized;
};
class Second : public First
{
public:
bool init() { return (*something*); }
};
You cannot check if initialized has been set or not, because it cannot represent the third state "undefined".
Solution 1
Protect the pure virtual function, make it return the initialized value and call it via a non-virtual wrapper
class First
{
public:
void init()
{
initialized = initImplementation();
// check initialized here
}
protected:
virtual bool initImplementation() = 0;
bool initialized;
};
Solution 2
Change initialized to an enumeration with the states undefined, non-initialized, initialized, protect the pure virtual function and call it via a non-virtual wrapper, that then checks if the variable has been set:
class First
{
public:
void init()
{
initImplementation();
// check initialized here
}
protected:
virtual void initImplementation() = 0;
enum
{
undefined,
initialized,
uninitialized
} initialized;
};
Solution 3
Get rid of initialized, just throw an exception in init() if something goes wrong. The caller will then know that something went wrong.
As a sidenote, you can throw also from the constructor.
Well, while the direct answer to your question is no. There is some technique you can employ to get a guaranteed call of your init function.
Let's say you have the following base class:
class Base
{
public:
virtual void init() = 0;
private:
bool initialized = false;
};
void Base::init()
{
std::cout << "Called from base!\n";
initialized = true;
}
And the following derived:
class Derived: public Base
{
friend class Enforcer<Derived>;
public:
void init() override
{
std::cout << "Called from derived!\n";
}
private:
Derived()
{
}
private:
using BaseClass = Base;
};
Look at the private constructor and the friend declaration: you can no more create this class without help of the Enforcer class(this step is not really required but it will really force any user of the Derived class to use Enforcer). And now we need to write the Enforcer class, here it is:
template<typename T>
class Enforcer: public T
{
public:
template<typename... Args>
Enforcer(Args&&... arg): T(std::forward<Args>(arg)...)
{
}
void init() override
{
T::init();
T::BaseClass::init();
}
};
The whole example on the ideone.
Yes it has its drawbacks(you need to add some additional stuff to the Derived class) but it solves the requirement pretty neatly, in my opinion.
Related
Im trying to define an interface (abstract class) which will "automatically" register any instance created to a global map, where the key is an uint8_t and the value is a pointer to the interface class.
All classes that will implement this interface already have a method to retrieve a unique id with a getId() method. I've tried the following approach, but it get warningsn when I use the (then) abstract method getId() in the c'tor and d'tor of the interface, which I can understand. But I get an error when I try to create an instance of LightZoneImpl because it has no implementation of getId().
What am I doing wrong here?
Note: This is a simplified example of the real thing, lots of other classes etc involved in the real thing.
class ILightZone; // forward
typedef std::map<uint8_t, ILightZone*> LightZoneMap;
extern LightZoneMap lightZoneMap;
/**
* #brief Interface defining a Lightzone operating node, automatically (de-)registered in the lightZoneMap
*
*/
class ILightZone {
public:
ILightZone() {
lightZoneMap[getId()] = this; // <== warning: pure virtual function called from c'tor
}
virtual ~ILightZone() {
lightZoneMap.erase(getId()); // <== warning: pure virtual function called from d'tor
}
virtual const uint8_t getId() const = 0;
virtual void setLightOn() = 0;
virtual void setLightOff() = 0;
virtual bool isLightOn() = 0;
virtual void setIntensity(const uint8_t percentage) = 0;
virtual uint8_t getIntensity() = 0;
};
class BaseNode {
public:
BaseNode(uint8_t nodeId) : nodeId(nodeId) {};
virtual ~BaseNode() {};
virtual const uint8_t getid() const { return nodeId; };
private:
uint8_t nodeId;
};
class LightZoneImpl : public ILightZone, public BaseNode {
public:
LightZoneImpl() {};
virtual ~LightZoneImpl() {};
using BaseNode::getId;
void setLightOn() override { /* implementation */};
void setLightOff() override { /* implementation */};
bool isLightOn() override { return false; };
void setIntensity(const uint8_t percentage) override { /* implementation */ };
uint8_t getIntensity() override { return 0; };
}
LightZoneImpl zone{12}; // <= error: cannot declare variable 'zone' to be of abstract type LightZoneImpl
Note2: The example below is modified to show the solution suggested below
class ILightZone; // forward
typedef std::map<uint8_t, ILightZone*> LightZoneMap;
extern LightZoneMap lightZoneMap;
/**
* #brief Interface defining a Lightzone operating node, automatically (de-)registered in the lightZoneMap
*
*/
class ILightZone {
public:
ILightZone(uint8_t nodeId) : nodeId(nodeId) {
lightZoneMap[nodeId] = this;
}
virtual ~ILightZone() {
lightZoneMap.erase(nodeId);
}
const uint8_t getId() const { return nodeId; };
virtual void setLightOn() = 0;
virtual void setLightOff() = 0;
virtual bool isLightOn() = 0;
virtual void setIntensity(const uint8_t percentage) = 0;
virtual uint8_t getIntensity() = 0;
private:
uint8_t nodeId;
};
class BaseNode {
public:
BaseNode(uint8_t nodeId) : nodeId(nodeId) {};
virtual ~BaseNode() {};
virtual const uint8_t getid() const { return nodeId; };
private:
uint8_t nodeId;
};
class LightZoneImpl : public ILightZone, public BaseNode {
public:
LightZoneImpl(uint8_t nodeId) : ILightZone(nodeId), BaseNode(nodeId) {};
virtual ~LightZoneImpl() {};
using BaseNode::getId;
void setLightOn() override { /* implementation */};
void setLightOff() override { /* implementation */};
bool isLightOn() override { return false; };
void setIntensity(const uint8_t percentage) override { /* implementation */ };
uint8_t getIntensity() override { return 0; };
}
LightZoneImpl zone{12}; // <= error: cannot declare variable 'zone' to be of abstract type LightZoneImpl
Virtual dispatch doesn't start using the derived-class function overrides until construction completes: at the time you hoped getId() would use the derived-class override, only part of the abstract base class had been constructed - the derived object didn't exist to have its functions called.
You can have derived classes or a factory function provide the id and operate on the map.
Elaboration/example as requested by Bascy...
You can think of the objects involved here as being a LightZoneImpl object in which an ILightZone base class object is embedded. To construct the LightZoneImpl, the base class must be constructed first... and while that's happening the derived-class object doesn't exist or have the invariants (guarantees about state) that the derived-class constructor sets up, so it's premature to call any derived class overrides of the virtual functions. For that reason, the C++ Standard says the base class virtual function implementations should continue to be called, but if they're unavailable because the function is pure virtual your program will terminate.
To work around this, you can do what Mooing Duck suggests in his comment, and have the derived class specify an id that the base class saves. That's probably best. You could also have a factory function that creates light zones, letting the derived-class constructor pass it down to the base class for storage/use:
std::unique_ptr<LightZoneImpl> lz_factory() {
static int id_ = 0;
if (id_ > 255)
throw std::runtime_error("too many lightzones");
return std::make_unique<LightZoneImpl>(id_++);
}
You'd then want to make the light zone constructors private and make the factory a friend.
I have a class hierarchy like this:
class Base
{
public:
void start() { init(); }
private:
virtual void init() = 0;
};
class Default : public Base
{
private:
virtual void init() override {/*default implementation*/};
};
class Special : public Default
{
private:
virtual void init() override final {/*specialized implementation*/};
}
Which works alright if I call start() on an object of type Special;
Now I have a case where in the implementation in the Special class I want to call the implementation of the Default class.
Normally that would work with Default::init();, but will fail here due to the Defaults declaration of this is private.
Obviously one solution is to change this from private to protected, but I'd like to ask if there is another way? Rather than allowing any child to call this function directly, I'd like to limit this to calls that are initiated via virtual functions already defined in the Base or Default class.
Is there some option or modifier that would allow member function calls to be only allowed from child classes if they are within (the same) overriding virtual member functions?
C++ doesn't provide means to achieve this directly, so you'd have to work around, e. g. in piece of code below.
Well, if you absolutely want to. I personally would rather just fall back to making the functions protected, document what they are intended for and when to be called, and then just trust the deriving classes to do the stuff right. That in the end keeps the interfaces cleaner and doesn't rely on a rather unusual (and perhaps ugly) pattern (actually passing this twice).
class Base
{
public:
virtual ~Base() { }
void start()
{
InitProxy p(*this);
init(p);
}
protected:
class InitProxy
{
public:
InitProxy(InitProxy const&) = delete;
void init()
{
m_base.Base::init(*this);
}
private:
friend class Base;
Base& m_base;
InitProxy(Base& base)
: m_base(base)
{ }
};
private:
virtual void init(InitProxy& proxy) { }
};
class Derived : public Base
{
void init(InitProxy& proxy) override
{
proxy.init();
}
};
You could let the proxy accept a member function pointer, if you want to apply this constraint to more than one function, so you wouldn't have to re-write the proxy for every function separately. Possibly you'd need to make a template from then, if function parameters differ.
Forward declare Special, and make it a friend of Default:
class Base
{
public:
void start() { init(); }
private:
virtual void init() = 0;
};
class Special; // Forward declaration
class Default : public Base
{
private:
virtual void init() override {/*default implementation*/}
friend class Special; // Friend declaration
};
class Special : public Default
{
private:
virtual void init() override final {
Default::init();
/*Other implementation*/
}
};
When trying to call a method setCurrentState Im getting the error:
StateMachine<Cow>::setCurrentState(std::shared_ptr<State<Cow>>)':
cannot convert argument 1 from 'std::shared_ptr<ChaseState>' to
'std::shared_ptr<State<Cow>>'
This indicates that a std::shared_ptr<ChaseState> is not a std::shared_ptr<State<Cow>> but why is it not?
The call to the function:
std::shared_ptr<ChaseState> initialState = std::make_shared<ChaseState>();
m_stateMachine->setCurrentState(initialState);
State.h
#pragma once
template <class entity_type>
class State
{
public:
virtual void enter(entity_type*) = 0;
virtual void execute(entity_type*) = 0;
virtual void exit(entity_type*) = 0;
};
ChaseState.h
class Cow;
class ChaseState : State<Cow>
{
public:
ChaseState();
// Inherited via State
virtual void enter(Cow*) override;
virtual void execute(Cow*) override;
virtual void exit(Cow*) override;
};
In my StateMachine I have private variable:
std::shared_ptr<State<entity_type>> m_currentState;
and the setCurrentState function:
void setCurrentState(std::shared_ptr<State<entity_type>> s) { m_currentState = s; }
As I understand the derived class ChaseState is a State (behause it inherits from state).
You need to declare your inheritance public. Class inheritance is private by default, meaning that you cannot cast from Derived to Base because the inheritance is not recognized outside of the class itself (same as how private members cannot be accessed outside the class).
To fix, make your inheritance public:
class ChaseState : public State<Cow>
// ^^^^^^
I have the following class hierarchy set up and would like the print() function of the non-singleton base object OtherBase to be called which in turn calls the printSymbol() from one of the child classes, in this case SingletonChild. I understand this is a complicated and somewhat unnecessary looking hierarchy and way of doing things but this is an assignment and I am required to do it in this way.
An example of my problem is as follows:
#include <iostream>
using namespace std;
class Object
{
virtual void print() = 0;
};
class SingletonBase : public Object
{
private:
static SingletonBase* theOnlyTrueInstance;
protected:
SingletonBase()
{
if(!theOnlyTrueInstance)
theOnlyTrueInstance = this;
}
virtual ~SingletonBase(){}
public:
static SingletonBase* instance()
{
if (!theOnlyTrueInstance) initInstance();
return theOnlyTrueInstance;
}
void print()
{ cout<<"Singleton"<<endl; }
static void initInstance()
{ new SingletonBase; }
};
SingletonBase* SingletonBase::theOnlyTrueInstance = 0;
class OtherBase : public Object
{
public:
virtual string printSymbol() = 0;
void print()
{ cout<<printSymbol(); }
};
class SingletonChild : public SingletonBase , public OtherBase
{
public:
string printSymbol()
{
return "Test";
}
static void initInstance()
{ new SingletonChild; }
};
int main() {
SingletonChild::initInstance();
OtherBase* test = (OtherBase*) SingletonChild::instance();
test->print();
return 0;
}
How can I get the instance test to call the print function of the one base class OtherBase and not the Singleton base class SingletonBase?
I have tried test->OtherBase::print(), but this did not work.
#MuhammadAhmad's answer is basically right. I would like to add that the main issue here is that a C-style cast is allowing you to do something that you really don't want to do. Because you can't statically cast a SingletonBase to an OtherBase, the C-style cast is doing a reinterpret_cast instead, and calling print() on the resulting pointer is undefined behavior. If you had used a static_cast, you would have gotten an error:
OtherBase* test = static_cast<OtherBase*>(SingletonChild::instance());
error: invalid static_cast from type ‘SingletonBase*’ to type ‘OtherBase*’
This may have led you to realize you needed to do things a bit differently. For example, you can use a dynamic_cast to cast sideways like this.
SingletonChild is inheriting it's instance method from SingletonBase, which is returning a pointer to SingletonBase.
So calling SingletonChild::instance(); will get you a SingletonBase*, which you can't simply cast to OtherBase*
Try casting it to SingletonChild* first, then to OtherBase*:
OtherBase* test = (OtherBase*)((SingletonChild*)SingletonChild::instance());
And then call the print method simply like this: test->print();
See the code on ideone.
EDIT:
You can also achieve this like this:
SingletonChild* test = (SingletonChild*)SingletonChild::instance();
test->OtherBase::print();
See this method in action too.
What you are trying to do is casting an object of type SingletonBase* to type OtherBase*, which is not possible because SingletonBase does not derive from OtherBase. If you had used dynamic_cast rather than old, deprecated C-style cast, you would have recognized this situation rather immediately.
To solve the issue, you need to modify the code as follows:
class Object
{
virtual void print() = 0;
};
class SingletonBase : public Object
{
private:
static Object* theOnlyTrueInstance;
protected:
SingletonBase()
{
if(!theOnlyTrueInstance)
theOnlyTrueInstance = this;
}
virtual ~SingletonBase(){}
public:
static Object* instance()
{
if (!theOnlyTrueInstance) initInstance();
return theOnlyTrueInstance;
}
void print()
{ cout<<"Singleton"<<endl; }
static void initInstance()
{ new SingletonBase; }
};
Object* SingletonBase::theOnlyTrueInstance = 0;
class OtherBase : public Object
{
public:
virtual string printSymbol() = 0;
void print()
{ cout<<printSymbol(); }
};
class SingletonChild : public SingletonBase , public OtherBase
{
public:
string printSymbol()
{
return "Test";
}
static void initInstance()
{ new SingletonChild; }
};
int main() {
SingletonChild::initInstance();
OtherBase* test = dynamic_cast<OtherBase*>(SingletonChild::instance());
test->print();
return 0;
}
You should avoid C-style casts, as you could end-up manipulating object like something they are not.
The content
The question
Example
Why do I need it
Hi.
The question
I am facing a problem. I have a class A that has a base B (is polymorphic). In B class is method Print(), wich is virtual. In A class is also Print(). virtual.
Lets say I am given an A type object (or pointer), stored in B variable
B * object = new A();
And by calling
object->Print();
It calls the method in A class, but I also want it to call method in B class.
Technically
I want to call the method for each child until i reach class that has no child
This can be done as follows:
Example
class A
{
public:
virtual void Print() const override
{
cout << "A" << endl;
}
};
class B : public A
{
public:
virtual void Print() const override
{
cout << "B" << endl;
A::Print(); // i do not want to call it here...
}
};
The problem is that I do want not to be forced to call the
A::Print();
Why
Yes, you might be asking, what is the deal...
I have very long inheritance chain. (lets say that there are like 15 - 20 classes in the inheritance chain).
In a game, each one does some little thing.
Lets say
class GameObject
{
public:
virtual void Update() const
{
//updates position, recounts it towards screen
}
};
class Character : public GameObject
{
public:
virtual void Update() const override
{
// Updates lives, movement
}
};
class Warrior : public Character
{
public:
virtual void Update() const override
{
// Updates armor, specific stuff
}
};
Now this example is very simplified. Problem is, that if i forget to add a call base::Update() Then I am worndering why does it not work. Looking for such a misstake is hard. I mean, if there any way around it?
Thank you very much indeed for any responses.
Have a nice day
If indeed every class must call the base function, one way to ensure the functionality is enforced is to use the template pattern.
class GameObject
{
public:
void Updater()
{
Update(); // this is a virtual call
GameObject::Update(); // now call base
}
virtual void Update() const
{
}
};
class Character : public GameObject
{
public:
virtual void Update() const override
{
// Updates lives, movement
}
};
class Warrior : public Character
{
public:
virtual void Update() const override
{
// Updates armor, specific stuff
}
};
class Character : public GameObject
{
public:
virtual void Update() const override
{
// Updates lives, movement
}
};
class Warrior : public Character
{
public:
virtual void Update() const override
{
// Updates armor, specific stuff
}
};
Then always call YourObject::Updater(); instead of YourObject::Update(). The Updater function will call your object's Update function, and then return and call the base class Update.
There was once a proposal to get all the bases of a given type (N2965) which gcc actually implemented in <tr2/type_traits>. So, if portability is not a concern and you happen to be using gcc, you can write a catch-all like so:
struct A {
virtual ~A() = default;
virtual void print() { print_all(*this); }
void print_one() { std::cout << "A\n"; }
protected:
template <class T>
void print_all(T& object) {
object.print_one();
print_all(object, typename std::tr2::bases<T>::type{});
}
template <class T, class... Bases>
void print_all(T& object, std::tr2::__reflection_typelist<Bases...> ) {
using swallow = int[];
(void)swallow{0,
(static_cast<Bases&>(object).print_one(), 0)...
};
}
};
This splits up print(), which prints everything, and print_one() which just prints the one specific type. You just have your print() call print_all() with itself:
struct B : A {
void print() override { print_all(*this); }
void print_one() { std::cout << "B\n"; }
};
struct C : B {
void print() override { print_all(*this); }
void print_one() { std::cout << "C\n"; }
};
Otherwise, you'll have to wait for one of the reflection proposals to get adopted.