I want to use child class constructor when parent object was given to a function.
class foo {
public:
virtual void doThing() { };
};
class bar : public foo {
public:
void doThing() override;
};
class bar2 : public foo {
public:
void doThing() override;
};
int main () {
bar obj;
bar2 obj2;
someFunction(&obj);
someFunction(&obj2);
}
void someFunction(foo *obj) {
//child object construction
}
If bar class object pointer was passed to a someFunction() then it would create new bar object inside function. Same thing with bar2 class and so on.
My question: is there a way to construct a child object when object's reference was given?
The typical way you do this is to provide a pure virtual "clone" method in foo, and then define it in the members.
The particularly good designers (A good designer is a lazy designer) use the Curiously Recursing Template Pattern (CRTP) to help this out.
class foo { public: virtual foo* clone() const=0; virtual ~foo(){}}
template <typename Derived>
class foo_helper : public foo
{
public:
virtual foo* clone() const
{
return new Derived(static_cast<const Derived&>(*this));
}
virtual ~foo_helper(){}
}
class Bar : foo_helper<Bar>
{
public:
virtual ~Bar(){}
}
see also:
http://katyscode.wordpress.com/2013/08/22/c-polymorphic-cloning-and-the-crtp-curiously-recurring-template-pattern/
Related
class Base
{
public:
virtual void f()
{
g();
}
virtual void g()
{
cout<<"base";
}
};
class Derived : public Base
{
public:
virtual void f()
{
Base::f();
}
virtual void g()
{
cout<<"derived";
}
};
int main()
{
Base *pBase = new Derived;
pBase->f();
return 0;
}
In this program I have kept both derived and base class functions as virtual. Is it possible call virtual functions of derived class through base class pointer and base class functions are not virtual.
Thanks in advance..
assuming functions in base class are not virtual
This can be achieved via type erasure. But there are caveats.
Your "base" class should decide between the two:
Being a view class (can't be called delete on or created by itself)
Being a resource owning class (implemented similar to 1, but stores a smart pointer).
Here is an example for case 1: https://godbolt.org/z/v5rTv3ac7
template <typename>
struct tag{};
class base
{
public:
base() = delete;
template <typename Derived>
explicit base(tag<Derived> t)
: _vTable(make_v_table(t))
{}
int foo() const { return _vTable.foo(*this); }
protected:
~base() = default;
private:
struct v_table
{
virtual int foo(const base &b) const = 0;
protected:
~v_table() = default;
};
template <typename Derived>
static const v_table& make_v_table(tag<Derived>){
struct : v_table
{
int foo(const base &b) const {
return static_cast<const Derived&>(b).foo();
}
} static const _vTable{};
return _vTable;
}
private:
const v_table& _vTable;
};
class derived : public base
{
public:
explicit derived()
: base(tag<derived>{})
{}
int foo() const { return 815; }
};
// example
#include <iostream>
int main(){
derived d{};
const base& b = d;
std::cout << b.foo() << '\n';
}
Take notice, that you can only take a pointer or a reference (cv-qualified) to a base class. The base class can't be created on its own.
Also tag<T> is needed to call a templated constructor.
DO NOT CALL DERIVED METHODS IN THE BASE CONSTRUCTOR OR DESTRUCTOR
Simple answer is no, if the function you are calling is not virtual. The Compiler would have no Idea that you are trying to call a function from the Derived Class, and won't make and I'm paraphrasing here since I do not know the proper term for,"Won't make proper entries in the Virtual Table".
class Base
{
public:
void f()
{
std::cout<<"Base f() Called\n";
g();
}
virtual void g()
{
std::cout<<"Base g()\n";
}
virtual ~Base(){std::cout<<"Base Destroyed\n";}
};
class Derived : public Base
{
public:
void f()
{
g();
}
virtual void g()
{
std::cout<<"Derived g()\n";
}
~Derived(){std::cout<<"Derived Destroyed\n";}
};
int main()
{
Derived* D1 = new Derived();
Base* B1 = D1;
B1->f();
delete B1;
return 0;
}
Have a look at the following code, I have not declared Base::f() as virtual,calling B1->f() calls the Base Method, but the base method calls a virtual function Base::g() and this allows the "Derived" method be called.
Have a look at this thread or this blogpost to understand Virtual Tables.
(1) and you must ALWAYS declare the destructor of a base class virtual when destroying Derived Object through a Base Pointer, else the resources used by the Derived Object will never get destroyed and it's memory will leak until the program closes.
Don't Take my word as gospel, I am simply passing on knowledge I have acquired from first hand experience, Except for (1), specially if you are not using smart pointers
I understand that the following code doesn't work -- can't convert base to foo.
Is there something I can do, or some pattern to employ which would get me close the behavior I'm trying to achieve in the code below? IOW, if I have a base class pointer to a derived type, how can I invoke a specific method that matches the derived type (not the base type)?
What patterns might I use? I looked into Curiously Recursive (or recurring) Template Pattern, however this imposed other limitations itself.
class base {};
class foo : public base {};
void method(const foo& f){}
int main(){
base* b = new foo();
method(*b);
}
The easiest way is probably to just make method() a virtual member function on foo:
class base {
public:
virtual void method() const = 0;
};
class foo : public base {
public:
void method() const override { }
};
int main(){
foo f;
base* b = &f;
b->method();
}
But if for some reason that is not possible (perhaps you don't have access to method() or perhaps you want to keep the logic in method() separate from foo) you could use a simplified version of the Visitor Pattern.
The visitor pattern relies on all the classes in your hierarchy having a virtual function to dispatch based on class type.
In your case you don't need double-dispatch so you don't actually need the visitor object and can just call your method function directly from a virtual dispatch function:
class base {
public:
virtual void dispatch() const = 0;
};
class foo : public base {
public:
void dispatch() const override;
};
void method(const foo& f){}
void foo::dispatch() const {
method(*this);
}
int main(){
foo f;
base* b = &f;
b->dispatch();
}
You have to remember that in most contexts the compiler doesn't know that your base pointer is actually of type foo.
Use virtual functions to solve these kinds of problems:
class base {
public:
virtual void func() const { /* A */ }
};
class foo : public base {
public:
void func() const override { /* B */ }
};
void method(const base& f) {
f.func();
}
int main(){
base* b = new foo();
method(*b);
}
Now, depending on the actual type of f, either A or B code will be executed in method.
I have this code,
class IFoo
{
public:
IFoo(){}
virtual ~IFoo(){}
virtual void fooFunc() = 0;
};
class Foo : public IFoo
{
public:
Foo(){}
virtual ~Foo(){}
virtual void fooFunc(){/*impl*/}
};
class Poop : public IFoo
{
public:
Poop(){}
virtual ~Poop(){}
virtual void fooFunc(){/*impl*/}
};
class Bar
{
public:
Bar(){}
~Bar(){}
void setFoo(Foo* foo){/*impl*/}
};
//in main
Poop* poop = new Poop;
Bar bar;
bar.setFoo(poop);
delete poop;
Compiling this code gives me an error message about invalid conversion. What kind of casting should I use for this?
Please advise. Many thanks!
Poop does not derive from Foo, so you cannot pass a Poop* where a Foo* is expected, and vice versa. Poop and Foo both derive from IFoo so you need to instead change setFoo() to accept an IFoo* instead of a Foo*:
void setFoo(IFoo* foo){/*impl*/}
I have some troubles understanding how to manage the access rights of virtual methods. I made two small code samples, but I can't understand how things work.
Code Sample 1
The first code contains 3 classes: a mother class Foo and two derived classes. The class Baz looks a little bit like a Composite. There's a virtual method, but it's protected.
class Foo
{
protected:
virtual void doIt() = 0;
};
class Bar : public Foo
{
protected:
void doIt()
{}
};
class Baz : public Foo
{
protected:
void doIt()
{
M_foo->doIt(); // Error here
}
private:
Foo* M_foo;
};
When trying to compile (Visual C++ 2010) this, I get an error: I can't call doIt from a pointer to Foo in the derived class. So, my understanding was "I can't call this method because it could actually call another one (e.g. the one of Bar) to which I have no right".
Code Sample 2
I decided to change a bit the design of the code and design a function instead of the virtual method. However, to access a protected method, I need to add friendship with my function.
class Foo
{
friend void doItPlease( Foo* foo);
protected:
virtual Foo* getChild() = 0;
};
class Bar : public Foo
{
protected:
Foo* getChild()
{ return 0;}
};
class Baz : public Foo
{
protected:
Foo* getChild()
{
return M_foo;
}
private:
Foo* M_foo;
};
void doItPlease( Foo* foo)
{
Foo* myFoo( foo->getChild() );
};
This code compiles fine. The problem is that I can't understand why: I have declared only the base class as friend, not the children classes and friendship is not inherited. But now, when I call getChild from the function, it is like I would call a method to which I have no right (the one in Baz e.g.).
Could someone explain me how are the rights related to virtual methods managed?
Those are the rules for protected. They allow access to the base class subobject, but not for any unrelated instances like yours.
If you google for protected, you will find advice to avoid it in the first place, use private and public only, the intermediate is quite rarely good.
The point is that you define privateness from base class' perspective. If some action is allowed from the outside, it's irrelevant that the unknown party is freestanding or happens to be a subclass. The only relevant attribute is it's being known to be trusted or not.
If the particular derived class is defined along with base, feel free to make it friend, just keep maintaining the rules.
class Foo
{
public:
friend class Baz;
protected:
virtual void doIt() = 0;
};
class Baz : public Foo
{
public:
Baz(Foo* foo)
: M_foo(foo)
{
}
protected:
void doIt()
{
M_foo->doIt();
}
private:
Foo* M_foo;
};
This could not work beacause Foo::doIt is an undifined virtual method method
class Baz : public Foo
{
protected:
void doIt()
{
Foo::doIt();
}
};
But if you have something like this it's should work fine
class Baz : public Foo
{
Baz()
{
M_foo = new Bar();
}
protected:
void doIt()
{
M_foo->doIt();
}
private:
Foo* M_foo;
};
I have a base class MyBase that contains a pure virtual function:
void PrintStartMessage() = 0
I want each derived class to call it in their constructor
then I put it in base class(MyBase) constructor
class MyBase
{
public:
virtual void PrintStartMessage() =0;
MyBase()
{
PrintStartMessage();
}
};
class Derived:public MyBase
{
public:
void PrintStartMessage(){
}
};
void main()
{
Derived derived;
}
but I get a linker error.
this is error message :
1>------ Build started: Project: s1, Configuration: Debug Win32 ------
1>Compiling...
1>s1.cpp
1>Linking...
1>s1.obj : error LNK2019: unresolved external symbol "public: virtual void __thiscall MyBase::PrintStartMessage(void)" (?PrintStartMessage#MyBase##UAEXXZ) referenced in function "public: __thiscall MyBase::MyBase(void)" (??0MyBase##QAE#XZ)
1>C:\Users\Shmuelian\Documents\Visual Studio 2008\Projects\s1\Debug\s1.exe : fatal error LNK1120: 1 unresolved externals
1>s1 - 2 error(s), 0 warning(s)
I want force to all derived classes to...
A- implement it
B- call it in their constructor
How I must do it?
There are many articles that explain why you should never call virtual functions in constructor and destructor in C++. Take a look here and here for details what happens behind the scene during such calls.
In short, objects are constructed from the base up to the derived. So when you try to call a virtual function from the base class constructor, overriding from derived classes hasn't yet happened because the derived constructors haven't been called yet.
Trying to call a pure abstract method from a derived while that object is still being constructed is unsafe. It's like trying to fill gas into a car but that car is still on the assembly line and the gas tank hasn't been put in yet.
The closest you can get to doing something like that is to fully construct your object first and then calling the method after:
template <typename T>
T construct_and_print()
{
T obj;
obj.PrintStartMessage();
return obj;
}
int main()
{
Derived derived = construct_and_print<Derived>();
}
You can't do it the way you imagine because you cannot call derived virtual functions from within the base class constructor—the object is not yet of the derived type. But you don't need to do this.
Calling PrintStartMessage after MyBase construction
Let's assume that you want to do something like this:
class MyBase {
public:
virtual void PrintStartMessage() = 0;
MyBase() {
printf("Doing MyBase initialization...\n");
PrintStartMessage(); // ⚠ UB: pure virtual function call ⚠
}
};
class Derived : public MyBase {
public:
virtual void PrintStartMessage() { printf("Starting Derived!\n"); }
};
That is, the desired output is:
Doing MyBase initialization...
Starting Derived!
But this is exactly what constructors are for! Just scrap the virtual function and make the constructor of Derived do the job:
class MyBase {
public:
MyBase() { printf("Doing MyBase initialization...\n"); }
};
class Derived : public MyBase {
public:
Derived() { printf("Starting Derived!\n"); }
};
The output is, well, what we would expect:
Doing MyBase initialization...
Starting Derived!
This doesn't enforce the derived classes to explicitly implement the PrintStartMessage functionality though. But on the other hand, think twice whether it is at all necessary, as they otherwise can always provide an empty implementation anyway.
Calling PrintStartMessage before MyBase construction
As said above, if you want to call PrintStartMessage before the Derived has been constructed, you cannot accomplish this because there is no yet a Derived object for PrintStartMessage to be called upon. It would make no sense to require PrintStartMessage to be a non-static member because it would have no access to any of the Derived data members.
A static function with factory function
Alternatively we can make it a static member like so:
class MyBase {
public:
MyBase() {
printf("Doing MyBase initialization...\n");
}
};
class Derived : public MyBase {
public:
static void PrintStartMessage() { printf("Derived specific message.\n"); }
};
A natural question arises of how it will be called?
There are two solution I can see: one is similar to that of #greatwolf, where you have to call it manually. But now, since it is a static member, you can call it before an instance of MyBase has been constructed:
template<class T>
T print_and_construct() {
T::PrintStartMessage();
return T();
}
int main() {
Derived derived = print_and_construct<Derived>();
}
The output will be
Derived specific message.
Doing MyBase initialization...
This approach does force all derived classes to implement PrintStartMessage. Unfortunately it's only true when we construct them with our factory function... which is a huge downside of this solution.
The second solution is to resort to the Curiously Recurring Template Pattern (CRTP). By telling MyBase the complete object type at compile time it can do the call from within the constructor:
template<class T>
class MyBase {
public:
MyBase() {
T::PrintStartMessage();
printf("Doing MyBase initialization...\n");
}
};
class Derived : public MyBase<Derived> {
public:
static void PrintStartMessage() { printf("Derived specific message.\n"); }
};
The output is as expected, without the need of using a dedicated factory function.
Accessing MyBase from within PrintStartMessage with CRTP
While MyBase is being executed, its already OK to access its members. We can make PrintStartMessage be able to access the MyBase that has called it:
template<class T>
class MyBase {
public:
MyBase() {
T::PrintStartMessage(this);
printf("Doing MyBase initialization...\n");
}
};
class Derived : public MyBase<Derived> {
public:
static void PrintStartMessage(MyBase<Derived> *p) {
// We can access p here
printf("Derived specific message.\n");
}
};
The following is also valid and very frequently used, albeit a bit dangerous:
template<class T>
class MyBase {
public:
MyBase() {
static_cast<T*>(this)->PrintStartMessage();
printf("Doing MyBase initialization...\n");
}
};
class Derived : public MyBase<Derived> {
public:
void PrintStartMessage() {
// We can access *this member functions here, but only those from MyBase
// or those of Derived who follow this same restriction. I.e. no
// Derived data members access as they have not yet been constructed.
printf("Derived specific message.\n");
}
};
No templates solution—redesign
Yet another option is to redesign your code a little. IMO this one is actually the preferred solution if you absolutely have to call an overridden PrintStartMessage from within MyBase construction.
This proposal is to separate Derived from MyBase, as follows:
class ICanPrintStartMessage {
public:
virtual ~ICanPrintStartMessage() {}
virtual void PrintStartMessage() = 0;
};
class MyBase {
public:
MyBase(ICanPrintStartMessage *p) : _p(p) {
_p->PrintStartMessage();
printf("Doing MyBase initialization...\n");
}
ICanPrintStartMessage *_p;
};
class Derived : public ICanPrintStartMessage {
public:
virtual void PrintStartMessage() { printf("Starting Derived!!!\n"); }
};
You initialize MyBase as follows:
int main() {
Derived d;
MyBase b(&d);
}
You shouldn't call a virtual function in a constructor. Period. You'll have to find some workaround, like making PrintStartMessage non-virtual and putting the call explicitly in every constructor.
If PrintStartMessage() was not a pure virtual function but a normal virtual function, the compiler would not complain about it. However you would still have to figure out why the derived version of PrintStartMessage() is not being called.
Since the derived class calls the base class's constructor before its own constructor, the derived class behaves like the base class and therefore calls the base class's function.
I know this is an old question, but I came across the same question while working on my program.
If your goal is to reduce code duplication by having the Base class handle the shared initialization code while requiring the Derived classes to specify the code unique to them in a pure virtual method, this is what I decided on.
#include <iostream>
class MyBase
{
public:
virtual void UniqueCode() = 0;
MyBase() {};
void init(MyBase & other)
{
std::cout << "Shared Code before the unique code" << std::endl;
other.UniqueCode();
std::cout << "Shared Code after the unique code" << std::endl << std::endl;
}
};
class FirstDerived : public MyBase
{
public:
FirstDerived() : MyBase() { init(*this); };
void UniqueCode()
{
std::cout << "Code Unique to First Derived Class" << std::endl;
}
private:
using MyBase::init;
};
class SecondDerived : public MyBase
{
public:
SecondDerived() : MyBase() { init(*this); };
void UniqueCode()
{
std::cout << "Code Unique to Second Derived Class" << std::endl;
}
private:
using MyBase::init;
};
int main()
{
FirstDerived first;
SecondDerived second;
}
The output is:
Shared Code before the unique code
Code Unique to First Derived Class
Shared Code after the unique code
Shared Code before the unique code
Code Unique to Second Derived Class
Shared Code after the unique code
Facing the same problem, I imaginated a (not perfect) solution. The idea is to provide a certificate to the base class that the pure virtual init function will be called after the construction.
class A
{
private:
static const int checkValue;
public:
A(int certificate);
A(const A& a);
virtual ~A();
virtual void init() = 0;
public:
template <typename T> static T create();
template <typeneme T> static T* create_p();
template <typename T, typename U1> static T create(const U1& u1);
template <typename T, typename U1> static T* create_p(const U1& u1);
//... all the required possibilities can be generated by prepro loops
};
const int A::checkValue = 159736482; // or any random value
A::A(int certificate)
{
assert(certificate == A::checkValue);
}
A::A(const A& a)
{}
A::~A()
{}
template <typename T>
T A::create()
{
T t(A::checkValue);
t.init();
return t;
}
template <typename T>
T* A::create_p()
{
T* t = new T(A::checkValue);
t->init();
return t;
}
template <typename T, typename U1>
T A::create(const U1& u1)
{
T t(A::checkValue, u1);
t.init();
return t;
}
template <typename T, typename U1>
T* A::create_p(const U1& u1)
{
T* t = new T(A::checkValue, u1);
t->init();
return t;
}
class B : public A
{
public:
B(int certificate);
B(const B& b);
virtual ~B();
virtual void init();
};
B::B(int certificate) :
A(certificate)
{}
B::B(const B& b) :
A(b)
{}
B::~B()
{}
void B::init()
{
std::cout << "call B::init()" << std::endl;
}
class C : public A
{
public:
C(int certificate, double x);
C(const C& c);
virtual ~C();
virtual void init();
private:
double x_;
};
C::C(int certificate, double x) :
A(certificate)
x_(x)
{}
C::C(const C& c) :
A(c)
x_(c.x_)
{}
C::~C()
{}
void C::init()
{
std::cout << "call C::init()" << std::endl;
}
Then, the user of the class can't construct an instance without giving the certificate, but the certificate can only be produced by the creation functions:
B b = create<B>(); // B::init is called
C c = create<C,double>(3.1415926535); // C::init is called
Moreover, the user can't create new classes inheriting from A B or C without implementing the certificate transmission in the constructor. Then, the base class A has the warranty that init will be called after construction.
I can offer a work around / "companion" to your abstract base class using MACROS rather than templates, or staying purely within the "natural" constraints of the language.
Create a base class with an init function e.g.:
class BaseClass
{
public:
BaseClass(){}
virtual ~BaseClass(){}
virtual void virtualInit( const int i=0 )=0;
};
Then, add a macro for a constructor. Note there is no reason to not add multiple constructor definitions here, or have multiple macros to choose from.
#define BASECLASS_INT_CONSTRUCTOR( clazz ) \
clazz( const int i ) \
{ \
virtualInit( i ); \
}
Finally, add the macro to your derivation:
class DervivedClass : public BaseClass
{
public:
DervivedClass();
BASECLASS_INT_CONSTRUCTOR( DervivedClass )
virtual ~DervivedClass();
void virtualInit( const int i=0 )
{
x_=i;
}
int x_;
};