I have a inheritance that the destructor of base class applies Template Method Pattern. The destructor has to do some works before calling the virtual clean function, and do some another works after calling.
We know that Never Call Virtual Functions during Construction or Destruction. So the following code definitely is not available.
class base
{
public:
virtual ~base()
{
// ... do something before do_clear()
do_clear();
// ... do something after do_clear()
}
private:
virtual void do_clear() = 0;
};
class d1
: public base
{
public:
d1() : m_x(new int) {}
~d1() {}
private:
virtual void do_clear()
{
delete m_x;
}
int *m_x;
};
But if I moved the destruction of process to the destructor of derived class, for example:
class base
{
public:
virtual ~base()
{
}
protected:
void clear()
{
// ... do something before do_clear()
do_clear();
// ... do something after do_clear()
}
private:
virtual void do_clear() = 0;
};
class d1
: public base
{
public:
d1() : m_x(new int) {}
~d1()
{
clear();
}
private:
virtual void do_clear()
{
delete m_x;
}
int *m_x;
};
If the client write that:
base *x = new d1;
delete x;
It will call ~d1(), then call base::clear(), eventually call the virtual function d1::do_clear() properly.
The base::clear() can been moved to public, and the client can make things safely by calling base::clear() before destruction. A precondition is the client must know and not forget to call, I think it isn't convenient and breaks encapsulation.
My question is:
Is the design dangerous/risk?
Is existing other better design for this?
There are two problems with your current design. The first is that it violates the rule of five/rule of zero. This means that ordinary usage of these classes is almost certain to result in memory leaks or double deletions.
The second problem is that you are using inheritance to model something that is probably better modelled with composition. base wants d1 to provide some extra functionality to its destructor, with the exact form of this functionality specified at run-time. The use of a replaceable interface is therefore internal to base, and so should not be externally visible.
Here is how I would write this code (using wheels::value_ptr):
struct D_interface {
//Providing virtual functions for run-time modifiable behaviour
virtual D_interface *clone() const = 0;
virtual ~D_interface(){}
};
struct D_Delete {
//Here is the code to call through to the virtual `D` object behaviour:
void operator()(D_interface *p) {
// ... do something before delete p;
delete p;
// ... do something after delete p;
}
//Put (pointers to) relevant data here,
//initialise them when constructing the `value_ptr`, or
//at a later stage with get_deleter
};
struct d1 : D_interface {
wheels::value_ptr<int> mx;
virtual D_interface *clone() const {
return new d1(*this);
}
};
//Nothing derives from `base`, because the polymorphism that is needed is internal
//to the implementation of `base`
//To add new functionality, add a new `D_interface` implementation.
class base
{
wheels::value_ptr<D_interface, wheels::DefaultCloner<D_interface>, D_Delete> D_impl;
public:
base(D_interface *D_impl)
: D_impl(D_impl)
{
}
};
For my part I think that this pattern it is sure because you need to implement the virtual function in the derived classes. This is the philosophy of virtual classes.
Related
I have the following situation:
#include <iostream>
class Base{
public:
Base() = default;
virtual void make_sure_im_called() = 0;
};
class Child : public Base {
public:
virtual void make_sure_im_called()
{
std::cout << "I was called as intended." << std::endl;
};
}
It is so that I want every class that derives from Base to implement make_sure_im_called() (which is successfully done by making it pure virtual). But how can I assert that someone deriving a new class from Base is also forced to call the function? It seems that everything I try from the base class will fail because of the missing implementation.
In C++ there is no build-in construct which does what you want, though, you can always enforce it yourself.
#include <iostream>
class Base{
public:
Base() = default;
void make_sure_im_called() {
before_make_sure_im_called();
// Your own code
after_make_sure_im_called();
}
protected:
// Hooks to be implemented
virtual void before_make_sure_im_called() = 0;
virtual void after_make_sure_im_called() = 0;
};
class Child : public Base {
protected:
virtual void before_make_sure_im_called() override
{
std::cout << "I was called as intended." << std::endl;
};
virtual void after_make_sure_im_called() override {}
}
This results in 2 virtual calls (most of the time, you can survive with 1 of them).
If someone calls make_sure_im_called, this now will call the pure virtual calls.
By making them protected, the chance of them being called is reduced as only derived classes can access them.
Enforcing this method being called in the lifespan of the instance.
The method make_sure_im_called can't be called from within the constructor of Base. There is no construction which can enforce this, though, you could let the program crash if this was not the case.
#include <iostream>
class Base{
public:
Base() = default;
~Base() { assert(_initialized && "Some message"); }
void make_sure_im_called() {
before_make_sure_im_called();
// Your own code
after_make_sure_im_called();
_initialized = true;
}
protected:
// Hooks to be implemented
virtual void before_make_sure_im_called() = 0;
virtual void after_make_sure_im_called() = 0;
private:
bool _initialized{false};
};
class Child : public Base {
protected:
virtual void before_make_sure_im_called() override {};
virtual void after_make_sure_im_called() override {}
}
By keeping the _initialized member, you can keep track of the method being called. In the Dtor, you can assert on this and crash the program if this is false (debug-builds only?). Exercise to the reader: get copy/move-construction/assignment right.
The solution might not be that elegant, though, at least it will be better than having nothing at all. One could even document this as part of the API.
I have defined a member variable as follows. Since the variable will not be passed around, so I decide to use scoped_ptr rather than shared_ptr here.
class ClassName
{
public:
ClassName()
{
Initialize();
}
virtual void Initialize() = 0;
protected:
boost::scoped_ptr<int> m_scpInt;
}
class ClassNameB : public ClassName
{
public:
virtual void Initialize()
{
m_scpInt.reset(new int(100));
}
}
Due to the limit of the scoped_ptr, if I decide to defer the initialization of the variable in a later time, the only option I get is to call reset.
Q1> Is this a good practice?
Q2> Otherwise, is there a better solution?
Thank you
/// Updated -1 ///
This is what I really want to do.
I want to enforce that each of the derived class define a function called Initialize and which in turn calls function InitializeVarA and InitializeVarB. As you indicate, that we cannot call virtual function in the constructor.
class ClassName
{
public:
ClassName()
{
}
virtual void Initialize()
{
InitializeVarA();
InitializeVarB();
}
protected:
virtual void InitializeVarA() {}
virtual void InitializeVarB() {}
}
class ClassNameB : public ClassName
{
public:
ClassNameB()
{
}
virtual void Initialize()
{
InitializeVarA();
InitializeVarB();
}
protected:
virtual void InitializeVarA() {}
virtual void InitializeVarB() {}
}
ClassNameB cb;
cb.Initialize();
Do I have a better solution than this?
Is this a good practice?
Using reset to reset a scoped pointer is fine.
Trying to initialise a derived class by calling a virtual function from the base class's constructor is not just bad practice; it's wrong. At that point, the dynamic type of the object is the base class, and the function is pure virtual, so calling it gives undefined behaviour.
Even if you made it non-pure, you still can't call the derived class's override at that point, so the pointer won't be reset.
Otherwise, is there a better solution?
You could do it in the derived class's constructor, which is invoked immediately after the base class's:
class Base {
public:
Base() { /* don't call any virtual functions here */ }
protected:
boost::scoped_ptr<int> p;
};
class Derived : public Base {
public:
Derived() {
p.reset(new int(100));
}
};
Or you could pass the allocated memory to the base class constructor and initialise the pointer from that. That's slightly dangerous though - you must make sure you initialise the pointer immediately, before anything that might throw an exception, or the memory might leak.
class Base {
public:
Base(int * p) : p(p) {}
private: // doesn't need to be protected now
// (unless something else in the derived class needs access)
boost::scoped_ptr<int> p;
};
class Derived : public Base {
public:
Derived() : Base(new int(100)) {}
};
In C++11, you could use unique_ptr, which is movable, to avoid that risk of a leak:
class Base {
public:
typedef std::unique_ptr<int> ptr;
Base(ptr && p) : p(p) {}
private:
ptr p;
};
class Derived : public Base {
public:
Derived() : Base(ptr(new int(100))) {}
};
So I have this kind of setup
class Base
{
public:
Base();
virtual void parse() = 0;
};
Base::Base()
{
parse();
}
class Sub : public Base
{
public:
Sub();
void parse();
};
Sub::Sub() : Base() {}
void Sub::parse()
{
// DO stuff
}
I'm wondering if there's anway I can do something similar to this, right now I'm getting an error that says I can't call a pure virtual function which makes sense. Are there any keywords out there that I can use to make this work?
I think making parse() just virtual and not pure virtual would work, but I would like the user to have to overwrite it.
Invoking virtual member functions in a constructor (or destructor) will never make you end up in an overridden version of that function in a derived class.
The reason is that base class constructors (destructors) are executed before (after) derived class' constructors (destructors). That means that the part of an object representing the derived class simply is not yet (not anymore) existing. And calling member functions on non-existing objects isn't possible.
You will need to implement a form of two-phase construction (which isn't built into the language) in order to do what you want. Usually that's done by having a wrapping class first fully construct a Sub object and only then call parse() on it.
The point here is that you can't call pure virtual functions in the constructor, and even if you would provide an implementation, only the Base classes' implementation would be used in the constructor.
The reason is simply that the constructor of Base is executed right at the start of Sub, so any virtual function call to Sub would be called on an incomplete object.
In general, there is no solution for this: You cannot dispatch virtual functions in constructors or destructors.
The resolution of a virtual function cannot find a function in a class
which hasn't been constructed. (Formally: the dynamic type of the
object is that of the constructor or destructor which is running.) So
you need some sort of post-constructor, which the language doesn't
support.
You can sort of work around it by using a dummy parameter, which calls
the function you need in its destructor, e.g.:
class Base
{
public:
class PostConstructor
{
Base* owner;
friend class Base;
public:
PostConstructor() : owner( NULL ) {}
~PostConstructor() { owner->parse(); }
};
Base( PostConstructor const& helper )
{
helper.owner = this;
}
};
class Derived : public Base
{
public:
Derived( PostConstructor const& helper = PostConstructor() )
: Base( helper )
{
}
};
or if the class has arguments:
class Base
{
std::string name;
public:
class PostConstructor
{
Base* owner;
std::string arg; // for example...
friend class Base;
public:
PostConstructor( std::string const& arg ) // implicit conversion!!
: owner( NULL ), arg( arg ) {}
~PostConstructor() { owner->parse(); }
operator std::string() const { return arg; }
};
Base( PostConstructor const& helper )
: name( helper )
{
helper.owner = this;
}
};
class Derived : public Base
{
public:
Derived( PostConstructor const& helper )
: Base( helper )
{
}
};
This works because the PostConstructor will be a temporary, destructed
at the end of the full expression (when Derived has been fully
constructed).
In both cases: the derived classes must co-operate (but they won't
compile if they don't). The trick can also fail if the class is
constructed in the middle of a more complicated expression. Something
like:
Derived(...).someFunction();
In this case, the end of the full expression will be after the return
from someFunction, which may be a little late to call parse().
Still, despite the limitations, I've found this useful on occasions.
Abstract or pure methods are a special case of virtual methods (All abstract or pure methods are virtual).
My previous answer is wrong, because I overlook the constructor. Constructor on C++, are not virtual, and does not allow to call virtual (abstract and not abstract methods), inside the constructors. If you where calling a non abstract overrided "parse" from another method that is not the constructor, will be fine.
The problem its not that the method its abstract, its that is called from a constructor.
#include <conio>
class Base
{
public:
// a constructor:
Base();
// "virtual and abstract" method:
virtual void parse() = 0;
// "virtual non abstract" method:
virtual void hello();
};
// Error: you cannot call a virtual method from a constructor,
// wheter is abstract or not:
Base::Base()
{
// error:
parse();
// error:
hello();
}
Base::hello()
{
cout << "Hello World\n";
}
class Sub : public Base
{
public:
Sub();
// forgot "virtual" here,
// other languages use "override" instead, here:
virtual void parse();
// another "overriden" methods:
virtual void parse();
};
// right: its important to call the base constructor,
// in this case:
Sub::Sub() : Base()
{
// ...
}
void Sub::parse()
{
// DO stuff
}
int main()
{
Base *MyBaseObject = new Base();
MyObject->parse();
Sub *MyObject = new Sub();
MyObject->parse();
return 0;
}
There is is a workaround for this. To call a virtual method,
like it was called from a constructor, Declaring a new method, that its called right after the constructor:
#include <conio>
class Base
{
public:
// a constructor:
Base();
// a "postconstructor" or "pseudoconstructor"
virtual void create();
// "virtual and abstract" method:
virtual void parse() = 0;
// "virtual non abstract" method:
virtual void hello();
};
// Error: you cannot call a virtual method from a constructor,
// wheter is abstract or not:
Base::Base()
{
// no virtual methods called here,
// wheter abstract or not
}
// its not a real constructor, just a virtual method:
void Sub::create()
{
// ...
}
Base::hello()
{
cout << "Hello World\n";
}
class Sub : public Base
{
public:
Sub();
virtual void create();
// forgot "virtual" here,
// other languages use "override" instead, here:
virtual void parse();
// another "overriden" methods:
virtual void parse();
};
// right: its important to call the base constructor,
// in this case:
Sub::Sub() : Base()
{
// ...
}
// its not a real constructor, just a virtual method:
void Sub::create() : create()
{
parse();
}
void Sub::parse()
{
// DO stuff
}
int main()
{
// this commented code, wont work
/*
Base *MyBaseObject = new Base();
MyObject->create();
MyObject->parse();
*/
// calling "pseudo-constructor",
// just after real constructor
Sub *MyObject = new Sub(); MyObject->create();
MyObject->parse();
return 0;
}
My mistake sorry.
I want to implement a derived class that should also implement an interface, that have a function that the base class can call. The following gives a warning as it is not safe to pass a this pointer to the base class constructor:
struct IInterface
{
void FuncToCall() = 0;
};
struct Base
{
Base(IInterface* inter) { m_inter = inter; }
void SomeFunc() { inter->FuncToCall(); }
IInterface* m_inter;
};
struct Derived : Base, IInterface
{
Derived() : Base(this) {}
FuncToCall() {}
};
What is the best way around this? I need to supply the interface as an argument to the base constructor, as it is not always the dervied class that is the interface; sometimes it may be a totally different class.
I could add a function to the base class, SetInterface(IInterface* inter), but I would like to avoid that.
You shold not publish this from the constructor, as your object is not yet initialized properly at that point. In this actual situation, though, it seems to be safe, since you are publishing it only to the base class, which only stores it and does not invoke it until some point later, by which time the construction will have been finished.
However, if you want to get rid of the warning, you could use a static factory method:
struct Base
{
public:
Base() { }
void setInterface(IInterface* inter) { m_inter = inter; }
void SomeFunc() { inter->FuncToCall(); }
IInterface* m_inter;
};
struct Derived : Base, IInterface
{
private:
Derived() : Base() {}
public:
static Derived* createInstance() {
Derived instance = new Derived();
instance->setInterface(instance);
return instance;
}
FuncToCall() {}
};
Note that the constructor of Derived is private to ensure that instantiation is done only via createInstance.
You can always defer the interface dereference:
struct IInterface
{
virtual ~IInterface();
virtual void FuncToCall() =0;
};
class Base
{
public:
virtual ~Base();
void SomeFunc() { GetInterface().FuncToCall(); }
private:
virtual IInterface& GetInterface() =0;
};
class Derived: public Base, public IInterface
{
public:
private:
virtual IInterface& GetInterface() { return *this; }
virtual void FuncToCall();
};
There is a limited set of operations that you can do (guaranteed by the standard) with a pointer to a yet uninitialized object, and storing it for further use is one of them. The compiler is probably warning as it is easy to misuse the received pointer in Base.
Beware that most uses of the pointer for other than storage will be undefined behavior, but the code above is correct.
What is quite funny is that you could get away with it by initializing it later on:
Derived::Derived(): Base()
{
this->setInter(this);
}
is fine, because all attributes have been initialized.
This way you won't have to change your whole design just to get away with the warning.
However, unless the setInter does not do anything with this apart some storage, you might access an object you did not fully initialized (so storing a hash value could be awkward).
how about:
struct IInterface
{
void FuncToCall() = 0;
IInterface* me() { return this; }
};
...
struct Derived : IInterface, Base
{
Derived() : IInterface(), Base(me()) {}
FuncToCall() {}
};
at the point we get to Base constructor IInterface is already initialized, so the call to me() is safe, and warning free
what about using protected: for IInterface* m_inter;
struct IInterface
{
virtual void FuncToCall() = 0;
};
struct Base
{
Base(IInterface* inter) { m_inter = inter; }
void SomeFunc() { m_inter->FuncToCall(); }
protected: // or `public:` since you are using `struct`
IInterface* m_inter;
};
struct Derived : Base, IInterface
{
//Derived() : Base(this) {} // not good to use `this` in the initialization list
Derived() : Base() { m_inter = static_cast<IInterface*>(this); }
FuncToCall() {}
};
I have a base class that I want to look like this:
class B
{
// should look like: int I() { return someConst; }
virtual int I() = 0;
public B() { something(I()); }
}
The point being to force deriving classes to override I and force it to be called when each object is constructed. This gets used to do some bookkeeping and I need to know what type of object is being constructed (but I otherwise treat the current object as the base class).
This doesn't work because C++ won't let you call an abstract virtual function from the constructor.
Is there a way to get the same effect?
Based on this link it would seem that the answer is there is no way to get what I want. However what it says is:
The short answer is: no. A base class doesn't know anything about what class it's derived from—and it's a good thing, too. [...] That is, the object doesn't officially become an instance of Derived1 until the constructor Derived1::Derived1 begins.
However in my case I don't want to know what it is but what it will become. In fact, I don't even care what I get back as long as I the user can (after the fact) map it to a class. So I could even use something like a return pointer and get away with it.
(now back to reading that link)
You can't call virtual methods from the constructor (or to be more precise, you can call them, but you'll end up calling the member function from the class currently being constructed)., the problem is that the derived object does not yet exist at that moment. There is very little you can do about it, calling virtual methods from the constructor polymorphically is simply out of the question.
You should rethink your design -- passing the constant as an argument to the constructor, for example.
class B
{
public:
explicit B(int i)
{
something(i);
}
};
See C++ faq for more. If you really want to call virtual functions during construction, read this.
Perhaps use a static factory method on each derived type? This is the usual way to construct exotic objects (read: those with very specific initialisation requirements) in .NET, which I have come to appreciate.
class Base
{
protected Base(int i)
{
// do stuff with i
}
}
class Derived : public Base
{
private Derived(int i)
: Base(i)
{
}
public Derived Create()
{
return new Derived(someConstantForThisDerivedType);
}
}
Calling virtual methods in base constructors is generally frowned upon, as you can never be certain of a particular method's behaviour, and (as somebody else already pointed out) derived constructors will not have yet been called.
That will not work as the derived class does not yet exist when the base class constructor is executed:
class Base
{
public:
Base()
{
// Will call Base::I and not Derived::I because
// Derived does not yet exist.
something(I());
}
virtual ~Base() = 0
{
}
virtual int I() const = 0;
};
class Derived : public Base
{
public:
Derived()
: Base()
{
}
virtual ~Derived()
{
}
virtual int I() const
{
return 42;
}
};
Instead you could add the arguments to the base class constructor:
class Base
{
public:
explicit Base(int i)
{
something(i);
}
virtual ~Base() = 0
{
}
};
class Derived : public Base
{
public:
Derived()
: Base(42)
{
}
virtual ~Derived()
{
}
};
Or if you're really fond of OOP you could also create a couple of additional classes:
class Base
{
public:
class BaseConstructorArgs
{
public:
virtual ~BaseConstructorArgs() = 0
{
}
virtual int I() const = 0;
};
explicit Base(const BaseConstructorArgs& args)
{
something(args.I());
}
virtual ~Base() = 0
{
}
};
class Derived : public Base
{
public:
class DerivedConstructorArgs : public BaseConstructorArgs
{
public:
virtual ~DerivedConstructorArgs()
{
}
virtual int I() const
{
return 42;
}
};
Derived()
: Base(DerivedConstructorArgs())
{
}
virtual ~Derived()
{
}
};
What you need is two-phase construction. Use the Universal Programmer's cure: Add another layer of indirection.