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.
Related
Can anyone let me know how to achieve:
the parameter of a method of a derived class being the parameter's
derived class (not the parameter's base class)?
This is what I want:
class Base{
public:
// Base class method has ParameterBase parameter
virtual void f(ParameterBase pb) = 0;
}
class Derived : public Base{
public:
// I want: Derived class method has ParameterDerived parameter;
void f(ParameterDerived pd){ //do something with pd; }
}
class ParameterBase{
// Base class of parameter;
}
class ParameterDerived : public ParameterBase{
// Derived class of parameter;
}
How to achieve above?
Do I have to use ParamterBase in the derived method's parameter list and dynamic_cast the parameter in the method body?
The feature you are asking for is called parameter type contra-variance. And C++ unfortunately, doesn't support it. C++ supports just the return type covariance. See here for a nice explanation.
Perhaps inconveniently, C++ does not permit us to write the function
marked hmm... above. C++’s classical OOP system supports “covariant
return types,” but it does not support “contravariant parameter
types.”
But you can use dynamic_cast<>() operator. But first, you must change the parameter type to pointer or reference, and add at least one virtual member (virtual destructor counts too) to your class ParameterBase to make compiler to create virtual method table for it. Here is the code with references. Pointers can be used instead.
class ParameterBase
{
public:
// To make compiler to create virtual method table.
virtual ~ParameterBase()
{}
};
class ParameterDerived : public ParameterBase
{
};
class Base
{
public:
// Pointers or references should be used here.
virtual void f(const ParameterBase& pb) = 0;
};
class Derived : public Base
{
public:
virtual void f(const ParameterBase& pb) override
{
// And here is the casting.
const ParameterDerived& pd=dynamic_cast<const ParameterDerived&>(pb);
}
};
int main()
{
Derived d;
ParameterDerived p;
d.f(p);
}
Supposing you want Derived to be called with ParameterDerived, but you also want to declare the interface in abstract base classes.
The interface MUST have the same parameter types, but you can still enforce the right parameter subclass with a dynamic_cast inside Derived::f
#include <iostream>
#include <string>
// interface
struct ParameterBase {
virtual ~ParameterBase() {};
};
struct Base {
virtual void f(ParameterBase *pb) = 0;
virtual ~Base() {};
};
// specific
struct ParameterDerived : public ParameterBase {
std::string name;
ParameterDerived(const std::string &name) : name(name) {}
ParameterDerived& operator=(const ParameterDerived& rhs) { name = rhs.name; }
~ParameterDerived() {};
};
struct Derived : public Base {
Derived(){}
Derived& operator=(const Derived &rhs) {}
virtual ~Derived(){}
void f(ParameterBase *pb) {
ParameterDerived *pd = dynamic_cast<ParameterDerived*>(pb);
if (pd) {
std::cout << "Derived object with derived parameter " << pd->name << std::endl;
} // else {throw std::exception("wrong parameter type");}
}
};
int main() {
Derived object;
ParameterDerived param("foo");
object.f(¶m);
}
The following example is from the book "Inside C++ object model"
class Abstract_base {
public:
virtual ~Abstract_base () = 0;
virtual void interface () const = 0;
virtual const char* mumble () const
{
return _mumble;
}
protected:
char *_mumble;
};
The author says if I want to initialize _mumble, the data member of the pure virtual base class, a "protected constructor" should be implemented.
But why protected? And why "public constructor" is not suitable for this class?
Thanks for your answers, and it would be perfect if there's an example.
It doesn't really matter, since you're not allowed to construct objects of the base class anyway. Making it protected serves only as a reminder of the fact that the class is supposed to be a base class; it's only cosmetics/documentation.
Consider
struct Base {
virtual ~Base() = 0;
protected:
Base() { std::puts("Base constructor"); }
};
Base::~Base() { std::puts("Base destructor"); }
struct Derived : Base {};
int main()
{
//Base b; // compiler error
Derived d;
Base *b = new Derived();
delete b;
}
Removing the protected doesn't change the meaning of the program in any way.
Abstract classes and construction of such
It doesn't matter if the constructor is public or protected, since an abstract class cannot be instantiated.
You must inherit from it in order to have it's constructor called, and since the Derived class calls the constructor of the abstract class it doesn't matter what protection level you choose, as long as the Derived class can access it.
One reason that one could possibly have for making it protected is to serve as a reminder that the class must be constructed through inheritance, but honestly that should be clear enough when seeing that it has pure virtual member-functions.
example snippet
struct B {
virtual void func () = 0;
virtual ~B () = 0 { };
};
B::~B () { }
struct D : B {
void func () override;
};
int main () {
B b; // will error, no matter if Bs ctor is 'public' or 'protected'
// due to pure virtual member-function
D d; // legal, D has overriden `void B::func ()`
}
A pure virtual class cannot be instantiated, so it doesn't make a difference if the constructor is public or protected.
A public constructor is syntactically correct. However, making it protected will carry a stronger indication that the class cannot be instantiated.
For an example: http://ideone.com/L66Prq
#include <iostream>
using namespace std;
class PublicAbstract {
public:
PublicAbstract() { }
virtual void doThings() =0;
};
class ProtectedAbstract {
protected:
ProtectedAbstract() { }
public:
virtual void doMoreThings() =0;
};
class B: public PublicAbstract {
public:
void doThings() { }
};
class C: public ProtectedAbstract {
public:
void doMoreThings() { }
};
int main() {
B b;
C c;
return 0;
}
A public constructor would not be very useful, since abstract classes cannot be instantiated in the first place.
A protected constructor makes sense: this way, a derived concrete class can provide its own public constructor that chains to the protected constructor of the base abstract class.
Protecetd ctor will make sure the ctor gets called by only the classes which derive from Abstract_base.
Public ctor is not suitable because the class contains a pure virtual method! How are you planning to instantiate a pure-virtual class if not via its child classes?
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.
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))) {}
};
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.