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))) {}
};
Related
In read in this post that you could override a virtual function with other default arguments, but that it is not smart to do. My case is slightly different from the question there. The function in my base class and the function in my derived class should do exactly the same only the default argument is different. How should I go about achieving this?
EDIT with some sort of code example what I think might work but violates what is said in the earlier mentioned post and doesn't seem very neat to me:
class base {
public:
//not sure about the virtual here
virtual void func(bool something = true) { /*Do some stuff*/};
};
class derived : public base {
public:
void func(bool something = false) override
{
base::func(something); /*Doesn't seem like the way to go for me */
}
};
One option is to explicitly overload the function, and not rely on default arguments
class Base
{
public:
virtual void func() {func(2);} // call func(int) with one default
void func(int value);
};
class Derived: public Base
{
public:
using Base::func; // so the function which accepts an argument is
// not hidden from users the class
virtual void func() {func(42);} // call Base::func(int) with different value
};
Depending on need, it may be easier for the default value to be a member that is set by the constructor.
class Base
{
public:
Base() : default_value(2) {};
void func() {func(default_value);}
void func(int value);
protected:
Base(int defaulted) : default_value(defaulted) {};
private:
int default_value;
};
class Derived: public Base
{
public:
Derived() : Base(42) {}; // set different default value in the constructor
};
Depending on your need (and given that the requirement is only that the function be supplied with different defaults, but are otherwise the same) you may wish to consider leaving the functions non-virtual.
You might have overload
class base {
public:
virtual ~base() = default;
virtual void func() { func(true); };
virtual void func(bool something) // Maybe this one no longer need to be virtual
{ /*Do some stuff*/ } // then using different name is appropriate
// (avoid hiding issues)
};
class derived : public base {
public:
using base::func;
void func() override { func(false); }
};
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.
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.