This compiles OK, but gives runtime error on the b->hello() call. My intention is to use dynamic type of the b pointer and call Inherited::hello() version.
Help :-)
#include <iostream>
#include <memory>
using namespace std;
class Base {
public:
static shared_ptr<Base> factory();
string hello(){};
virtual ~Base() {};
protected:
Base(){};
};
class InheritedA : public Base{
friend class Base;
public:
string hello() {return "I am iA";}
protected:
InheritedA() {};
};
shared_ptr<Base> Base::factory() {
shared_ptr<Base> ptrB;
shared_ptr<InheritedA> ptrA;
ptrA = shared_ptr<InheritedA>(new InheritedA);
ptrB = dynamic_pointer_cast<Base>(ptrA);
return ptrB;
};
int main() {
shared_ptr<Base> b;
b = Base::factory();
cout << b->hello();
return 0;
}
You are forgetting one very important thing when it comes to polymorphism and overriding base-class functions: The functions must be virtual.
Since your function isn't virtual you call the Base::hello function, and since it doesn't return anything you will have undefined behavior, leading to the crash you experience.
You can ask the compiler to help you detect such cases by using the override specifier:
class InheritedA : public Base{
friend class Base;
public:
string hello() override // Tell the compiler that this function should
// override the function from the parent class
{return "I am iA";}
protected:
InheritedA() {};
};
If you use the override specifier the compiler will issue an error if the function is not virtual.
Besides marking the base class function virtual, you really should either return something, anything, from the function, or make it abstract:
class Base {
public:
static shared_ptr<Base> factory();
// Make the function a pure abstract function that must be overridden
virtual string hello() = 0;
virtual ~Base() {};
protected:
Base(){};
};
Obviously - virtual was missing in Base::hello() declaration, also override after InheritedA::hello() .
#include <iostream>
#include <memory>
using namespace std;
class Base {
public:
static shared_ptr<Base> factory();
virtual string hello(){};
virtual ~Base() {};
protected:
Base(){};
};
class InheritedA : public Base{
friend class Base;
public:
string hello() override {return "I am iA";}
protected:
InheritedA() {};
};
shared_ptr<Base> Base::factory() {
shared_ptr<Base> ptrB;
shared_ptr<InheritedA> ptrA;
ptrA = shared_ptr<InheritedA>(new InheritedA);
//some very complex stuff here
ptrB = dynamic_pointer_cast<Base>(ptrA);
return ptrB;
};
int main() {
shared_ptr<Base> b;
b = Base::factory();
cout << b->hello();
return 0;
}
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 need to copy an object of a polymorphic class having a base pointer. I know that I can implement a virtual method for this. But what if the base class should not be abstract? Leaving the method without pure-specifier can lead to run-time bugs, if you forget reimplement it in the derived. It's uncomfortable. What is the best way to handle this?
There are good reasons why you should never want to instantiate a base class.
If you do need to make a empty final class use the following.
class IBase
{
virtual void SharedCode()
{
1 + 1;
/// code here
};
virtual void AbstractDecalration() = 0;
};
class Base final: IBase
{
void AbstractDecalration() override;
};
Base b{};
All Future Derived classes will be able to use the SharedCode of IBase and you will have a Instantiated class of Base that is final. This is for future proofing your code base.
However I realize that is not the question you asked so here is a implementation were I use a simple check to the vtable pointer of the class to see if I have the correct class.
This is a runtime check and doesn't work across libraries use dynamic_assert if that is the case.
#include <memory>
#include <type_traits>
#include <assert.h>
class Base {
public:
auto clone() const
{
return std::unique_ptr<Base>(this->clone_impl());
}
private:
virtual Base* clone_impl() const
{
Base b{};
int* bVtablePtr = (int*)((int*)&b)[0];
int* thisVtablePtr = (int*)((int*)this)[0];
assert(bVtablePtr == thisVtablePtr);
return new Base(*this);
}
};
class Derived : public Base
{
auto clone() const
{
return std::unique_ptr<Derived>(this->clone_impl());
}
virtual Derived* clone_impl() const
{
return new Derived();
}
};
class Falty : public Base{};
int main(){
std::unique_ptr<Derived> good(new Derived());
std::unique_ptr<Falty> falty(new Falty());
good->clone(); // oke
falty->clone(); // this function asserts at runtime
}
Note the private clone_impl and public unique_ptr retuning clone method.
Very usefull to prevent memory leaks in your code
You can achieve what you want by introducing another abstract base class plus using CRPT for clone function. Then, clone will be automatically implemented in all derived classes "for free" (without manual retyping). Example:
struct Abstract
{
virtual ~Abstract() {}
virtual Abstract* clone() const = 0;
virtual void say() const = 0;
};
template <typename B, typename D>
struct AbstractCloneable : B
{
virtual B* clone() const override
{
return new D(static_cast<const D&>(*this));
}
};
// original base class
struct Base : AbstractCloneable<Abstract, Base>
{
virtual void say() const override
{
std::cout << "Base" << std::endl;
}
};
// original derived class #1
struct Derived1 : AbstractCloneable<Base, Derived1>
{
virtual void say() const override
{
std::cout << "Derived1" << std::endl;
}
};
And a test program:
int main()
{
std::unique_ptr<Abstract> ptr1 = std::make_unique<Base>();
ptr1->say();
std::unique_ptr<Abstract> ptr1_copy{ ptr1->clone() };
ptr1_copy->say();
std::unique_ptr<Abstract> ptr2 = std::make_unique<Derived1>();
ptr2->say();
std::unique_ptr<Abstract> ptr2_copy{ ptr2->clone() };
ptr2_copy->say();
}
Which outputs:
Base
Base
Derived1
Derived1
Live demo: https://godbolt.org/z/3FeSTd
See this article for more details and explanations: C++: Polymorphic cloning and the CRTP (Curiously Recurring Template Pattern).
I spent a lot of time trying to figure out why my code displays "Derived3" after I run it and I cannot understand it at all. From what I have read here on many posts, dynamic_cast should somehow say whether a pointer (in this case b) is (in this case) Derived2 or not. However, it passed the condition and when it should print out the display() function from Derived2 class, it strangely displayes the one from the Derived3 class. I am just wondering why the program displays "Derived 3" instead of not showing anything, since b pointer is clearly not pointing to a Derived2 object.
#include <iostream>
using namespace std;
class Base
{
int b;
public:
virtual void display()
{
cout<<"Base"<<endl;
}
};
class Derived: virtual public Base{
public:
void display()
{
cout<<"Derived"<<endl;
}
};
class Derived2: virtual public Base{
public:
void display()
{
cout<<"Derived 2"<<endl;
}
};
class Derived3:public Derived,public Derived2{
public:
void display()
{
cout<<"Derived 3"<<endl;
}
};
int main()
{
Base *b = new Derived3();
Derived2 *aux = dynamic_cast<Derived2*>(b);
if(aux)
{
aux->display();
}
return 0;
}
However, after editing the code a little bit, it works as it should be.
#include <iostream>
using namespace std;
class Base
{
int b;
public:
virtual void display()
{
cout<<"Base"<<endl;
}
};
class Derived: public Base{
public:
void display()
{
cout<<"Derived"<<endl;
}
};
class Derived2: public Base{
public:
void display()
{
cout<<"Derived 2"<<endl;
}
};
class Derived3:public Base{
public:
void display()
{
cout<<"Derived 3"<<endl;
}
};
int main()
{
Base *b = new Derived3();
Derived2 *aux = dynamic_cast<Derived2*>(b);
if(aux)
{
aux->display();
}
return 0;
}
Inheritance is a "Is-a" relationship.
Every Derived is both a Derived and a Base. By that pattern, every Derived3 is a Derived3, a Derived2, a Derived and a Base at the same time.
It would thus not make sense for that cast to fail.
The output is then finally the result of a normal virtual function call on a Derived2*. This is no different than in the most trivial example of inheritance, like in this snippet:
#include <iostream>
struct A {
virtual void fun() const {
std::cout << 'A';
}
};
struct B : A {
void fun() const {
std::cout << 'B';
}
};
int main () {
const A &a = B();
a.fun(); // prints 'B'
}
If you have a pointer or reference to some base class, a virtual function call will resolve to the actual type of the object it is called on. In your case, that's a Derived2* pointing to a child-class of type Derived3, so the function is looked up in the latter.
Keep in mind that the dynamic_cast only changes the type of the pointer, not the type of the object it points to!
However, it passed the condition and when it should print out the display() function from Derived2 class, it strangely displayes the one from the Derived3 class.
That's because of dynamic dispatch. Remember that display() is declared to be a virtual member function. It continues to be a virtual member function for all the derived classes.
Even though you cast the pointer from Base* to Derived*, the underlying object is still a Derived3. Hence, the dynamic dispatch mechanism calls Derived3::display().
Derived3::display() will also be called if you use:
Base *b = new Derived3();
b->display();
I have a homework for my programming course that asks me to designs an abstract from whom derive two classes, and from those two derived classes derives another class.
This brings the Deadly Diamond of Death problem. Which can be solved by virtual inheritance, though I need instance the objects of my first two classes to a pointer of my abstract class. And this can't be done with any kind of virtual inheritance. So, if there is a way to specify the base class from which the multiple inheritance class will derive, it would be astronomically useful.
Example:
#include <iostream>
using namespace std;
class Base {
public:
virtual void foo(){};
virtual void bar(){};
};
class Der1 : public Base {
public:
virtual void foo();
};
void Der1::foo()
{
cout << "Der1::foo()" << endl;
}
class Der2 : public Base {
public:
virtual void bar();
};
void Der2::bar()
{
cout << "Der2::bar()" << endl;
}
class Join : virtual Der1, virtual Der2 {
private:
int atribb;
};
int main()
{
Base* obj = new Join();
((Der1 *)(obj))->foo();
}
Compiler error:
nueve.cpp: In function ‘int main()’:
nueve.cpp:43:30: error: ‘Base’ is an ambiguous base of ‘Join’
Base* obj = new Join();
Use virtual inheritance.
class Der1 : public virtual Base {
public:
virtual void foo();
};
class Der2 : public virtual Base {
public:
virtual void bar();
};
If virtual is declared while deriving from base class, as shown in below example, the most derived class object contains only one base class sub object, which helps in resolving the ambiguity in your case.
After doing some code changes, your final executable code:
Code changes in below sample:
Added vitual key word, while deriving the child classes.
Removed "virtual" keyword while deriving most derived class.
Modified main to invoke the member function properly.
#include <iostream>
using namespace std;
class Base {
public:
virtual void foo(){};
virtual void bar(){};
};
class Der1 : public virtual Base {
public:
virtual void foo();
};
void Der1::foo()
{
cout << "Der1::foo()" << endl;
}
class Der2 : public virtual Base {
public:
virtual void bar();
};
void Der2::bar()
{
cout << "Der2::bar()" << endl;
}
class Join : public Der1, public Der2 {
private:
int atribb;
};
int main()
{
Base* obj = new Join();
obj->foo();
}
It's not clear what you're asking for, although you seem to be saying that virtual inheritance from Base is not suitable. So, assuming that's correct, you can replace Base* obj = new Join(); with Base* obj = (Der1*)new Join(); and you'll get a pointer to the Base object that's the base of Der1. Similarly, you can replace it with Base* obj = (Der2*)new Join(); and you'll get a pointer to the Base object thats the base of Der2.
I'm facing the following situation:
class Base{
virtual void Stuff() = 0;
};
class ConcreteA : public Base{
void Stuff() {};
};
class ConcreteB : public Base{
void Stuff() {};
};
class Context {
Base exec() {
ConcreteA conc_a();
return a;
}
};
Of course the compiler gives me an error since Base is abstract. However, I'd need that exec() return a Base type. I know that I can make the compiler happy using pointers or references, but since the object ConcreteA is created in exec(), returning by value is the best way to avoid dangling references or pointer with undefined ownership.
Is there a way to avoid using pointers or references to handle this kind of situations?
This looks like a perfect, simple use case for std::unique_ptr. Here is a C++14 example:
#include <memory>
#include <iostream>
class Base{
public:
virtual ~Base() {}
virtual void Stuff() = 0;
};
class ConcreteA : public Base{
void Stuff() { std::cout << "ConcreteA::Stuff\n"; };
};
class ConcreteB : public Base{
void Stuff() { std::cout << "ConcreteB::Stuff\n";};
};
class Context {
public:
std::unique_ptr<Base> exec() {
return std::make_unique<ConcreteA>();
}
};
int main()
{
Context c;
auto base_ptr = c.exec();
base_ptr->Stuff();
}
Memory is automatically deleted when base_ptr in main goes out of scope.
Note that I also made the Base destructor virtual. Perhaps you just left it out in your code example for the sake of brevity, but its importance should be stressed, and I think it should be kept even in short example code.