Accessing Derived class function through Base class Pointer without dynamic casting - c++

I am trying to find a way to access a function of the derived class through the base pointer without dynamic casting. I have tried the visitor pattern as suggested in this post, but it seems like it does not work for templated Derived class. Here is what I have:
#include <iostream>
#include <memory>
class Base
{
public:
virtual print() = 0;
};
template<class T>
class Derived final : public Base
{
private:
T value;
public:
Derived() = default;
explicit Derived(const T& data) : value{data} {}
T get_value () {return this->value;}
void print() {std::cout << value << std::endl;}
~Derived() {}
};
int main()
{
std::shared_ptr<Base> ptr_one = std::make_shared<Derived<int>>(3);
std::shared_ptr<Base> ptr_two = std::make_shared<Derived<int>>(3);
auto value = ptr_one->get_value(); // This will cause an error.
auto value_2 = ptr_two->get_value() // This will cause an error.
std::cout << value == value_2 << std::endl; // This is my final goal. Being able to compare the underlying data.
return 0;
}
My final goal is being able to compare the underlying data of two instances of the Derived class. Is there any way to achieve such task?

Related

Why inheritance doesn’t work inside methods? [duplicate]

This question already has answers here:
Why does an overridden function in the derived class hide other overloads of the base class?
(4 answers)
Closed 1 year ago.
This does not compile:
struct Base
{
void something( int a ) { }
};
struct Derived : public Base
{
static void something()
{
std::unique_ptr<Derived> pointer = std::make_unique<Derived>();
pointer->something( 11 );
}
};
It’s possible to fix with using Base::something but still, is it possible to make inheritance work as advertised even inside methods?
By using the same name for the function in the derived class you hide the symbol from the base class.
You can solve it by pulling in the name from the base class with the using statement:
struct Derived : public Base
{
// Also use the symbol something from the Base class
using Base::something;
static void something()
{
std::unique_ptr<Derived> pointer = std::make_unique<Derived>();
pointer->something( 11 );
}
};
I'm not exactly sure what you are trying to accomplish. I added virtual, and changed the name of the Derived something class function, and put in two variants. One variant calls through virtual inheritance, the other calls Base class member function directly.
#include <iostream>
using std::cout;
namespace {
struct Base {
virtual ~Base();
virtual void something(int a) { std::cout << "Base a:" << a << "\n"; }
};
Base::~Base() = default;
struct Derived : Base {
void something(int b) override { std::cout << "Derived b:" << b << "\n"; }
static void action() {
std::unique_ptr<Derived> pointer = std::make_unique<Derived>();
pointer->something(11);
}
static void other_action() {
std::unique_ptr<Derived> pointer = std::make_unique<Derived>();
pointer->Base::something(11);
}
};
} // anon
int main() {
Derived::action();
Derived::other_action();
}

How to rewrite code not to call virtual function from the constructor

So shortly the situation is like this
class Base
{
public:
Base() { setZero();}
virtual void setZero() {std::cout << "Set all Base class values to zeros (default) values";}
};
class Derived : public Base
{
public:
Derived () { }
void setZero() override {
Base::setZero();
std::cout << "Set all Derived class values to zeros (default) values";
}
};
setZero is public an is called form different places, also it has some logic, not just assignments, as Base and Derived classes are quite large.
But it's all doesn't work as intended as dynamic binding doesn't work when function is called from the constructor.
I see the solution to duplicate code from setZero to the consructors, but duplication of code is a bad thing. Is there some other solutions?
You might have factory to have "post-call", something like:
template <typename T, typename ... Ts>
T CreateBaseType(Ts&&... args)
{
T t(std::forward<Ts>(args)...);
t.setZero();
return t;
}
TL;DR - two phase construction sucks. Try to make your constructors construct stuff, and not call any virtual methods, or require it in order to function.
If you want initialization to occur after object construction (including vtables), you need to have a separate initialization phase on your objects.
A probably better way to handle this is this:
class Base
{
int x = 0; // notice the =0 here
public:
Base() {} // nothing
virtual setZero() {*this = Base{};} // use operator= to assign zeros
};
class Derived : public Base
{
double d = 0.; // notice the = 0. here
public:
Derived () { } // nothing
void setZero() override {*this = Derived{};}
};
we can avoid rewriting setZero as well:
template<class D, class B=void>
struct SetZero:B {
void setZero() override {
*static_cast<D*>(this) = D{};
}
};
template<class D>
struct SetZero<D,void> {
virtual void setZero() {
*static_cast<D*>(this) = D{};
}
};
now we can:
class Base:public SetZero<Base>
{
int x = 0; // notice the =0 here
public:
A() {} // nothing
};
class Derived : public SetZero<Derived, Base>
{
double d = 0.; // notice the = 0. here
public:
Derived () { } // nothing
};
and setZero is written for us.
The DRY here is that default construction zeros, and we put the zeros right next to where we declare variables. setZero then just becomes a helper method to copy over yourself with a default constructed object.
Now, exposing value semantics copy/move operations on a class with a vtable is a bad plan. So you probably want to make the copy/move protected and add friend declarations.
template<class D, class B=void>
struct SetZero:B {
void setZero() override {
*static_cast<D*>(this) = D{};
}
SetZero()=default;
protected:
SetZero(SetZero&&)=default;
SetZero& operator=(SetZero&&)=default;
SetZero(SetZero const&)=default;
SetZero& operator=(SetZero const&)=default;
~SetZero() override=default;
};
template<class D>
struct SetZero<D,void> {
virtual void setZero() {
*static_cast<D*>(this) = D{};
}
SetZero()=default;
protected:
SetZero(SetZero&&)=default;
SetZero& operator=(SetZero&&)=default;
SetZero(SetZero const&)=default;
SetZero& operator=(SetZero const&)=default;
virtual ~SetZero()=default;
};
so those get longer.
In Base and Derived as they have vtables, you are recommended to add
protected:
Derived(Derived&&)=default;
Derived& operator=(Derived&&)=default;
};
to block external access to move/copy construct and move/copy assign. This is advised regardless of how you write setZero (any such move/copy is going to risk slicing, so exposing it to all users of your class is a bad plan. Here I make it protected, because setZero relies on it to make zeroing DRY.)
Another approach is a two-phase construction. In it, we mark all "raw" constructors are protected.
class Base {
int x;
protected:
Base() {} // nothing
public:
virtual setZero() { x = 0; }
};
we then add a non-constructor constructor:
class Base {
int x;
protected:
Base() {} // nothing
public:
template<class...Ts>
static Base Construct(Ts&&...ts){
Base b{std::forward<Ts>(ts)...};
b.setZero();
}
virtual setZero() { x = 0; }
};
and external users have to Base::Construct to get a Base object. This sort of sucks, because our type is no longer regular, but we already have vtable, which makes it unlikely to be regular in the first place.
We can CRTP it;
template<class D, class B=void>
struct TwoPhaseConstruct:B {
template<class...Ts>
D Construct(Ts&&...ts) {
D d{std::forward<Ts>(ts...));
d.setZero();
return d;
}
};
template<class D>
struct TwoPhaseConstruct<D,void> {
template<class...Ts>
D Construct(Ts&&...ts) {
D d{std::forward<Ts>(ts...));
d.setZero();
return d;
}
};
class Base:public TwoPhaseConstruct<Base> {
int x;
protected:
Base() {} // nothing
public:
virtual setZero() { x = 0; }
};
class Derived:public TwoPhaseConstruct<Derived, Base> {
int y;
protected:
Derived() {} // nothing
public:
virtual setZero() { Base::setZero(); y = 0; }
};
and here goes down the rabbit hole, if you want to make_shared or similar we have to add a helper type.
template<class F>
struct constructor_t {
F f;
template<std::constructible_from<std::invoke_result_t<F const&>> T>
operator T()const&{ f(); }
template<std::constructible_from<std::invoke_result_t<F&&>> T>
operator T()&&{ std::move(f)(); }
};
which lets us
auto pBase = std::make_shared<Base>( constructor_t{[]{ return Base::Construct(); }} );
but how far down the rabbit hole do you want to go?
Alternatively to the other answers, separating functionality from API lets you use the general flow you want while dodging the whole "using the vtable in the constructor" issue.
class Base
{
public:
Base() {
setZeroImpl_();
}
virtual void setZero() {
setZeroImpl_();
}
private:
void setZeroImpl_() {
std::cout << "Set all Base class values to zeros (default) values";
}
};
class Derived : public Base
{
public:
Derived () {
setZeroImpl_();
}
void setZero() override {
Base::setZero();
setZeroImpl_();
}
private:
void setZeroImpl_() {
std::cout << "Set all Derived class values to zeros (default) values";
}
};
You could solve it this way:
#include <iostream>
class Base
{
public:
Base() { Base::setZero();}
virtual void setZero() {std::cout << "Set all Base class values to zeros (default) values\n";}
protected:
Base(bool) {};
};
class Derived : public Base
{
public:
Derived () : Base(true) { Derived::setZero(); }
void setZero() override {
Base::setZero();
std::cout << "Set all Derived class values to zeros (default) values\n";
}
};
What I have done, is the following:
Make clear which setZero() method is called by which constructor
Added call to setZero()also from the Derived constructor
Added a protected Base constructor that does not call its setZero() method, and calling this constructor from Derived's constructor, so that Base::setZero()is called exactly once during creation of a Derived object.
By doing it this way, you can create Base or Derived and call zerZero() as intended.
You could implement a simple factory method in your Derived class and remove the setZero() calls from the constructors alltogether. Then making the constructors non-public will tell consumers of the class to use the factory method for proper instantiation instead of the constructor. Something like this:
class Base
{
protected:
Base() { }
virtual void setZero() {std::cout << "Set all Base class values to zeros (default) values";}
};
class Derived : public Base
{
public:
static Derived createInstance()
{
Derived derived;
derived.setZero();
return derived;
}
private:
Derived() { }
void setZero() override {
Base::setZero();
std::cout << "Set all Derived class values to zeros (default) values";
}
};
And then create your instance of Derived somehow like this:
int main()
{
Derived derived = Derived::createInstance();
// do something...
return 0;
}
With this approach you can also make sure that no one can create an instance of your class that is not in a valid state.
Note: Don't know if you use the base class at some places directly but if this is the case you could provide a factory method for it as well.
If I understand your question correctly, then what you need to do is below simply
#include <iostream>
using std::cout;
using std::endl;
class Base
{
void init() {std::cout << "Set all Base class values to zeros (default) values" << endl;}
public:
Base() {init(); }
virtual void setZero() {init();}
};
class Derived : public Base
{
void init() { std::cout << "Set all Derived class values to zeros (default) values" << endl; }
public:
Derived () { init(); }
void setZero() override {
Base::setZero();
init();
}
};
int main()
{
Derived d1;
cout << endl;
d1.setZero();
}
You wrote the below statement for your code
But it's all doesn't work as intended as dynamic binding doesn't work when function is called from the constructor.
Yes, the virtual behavior will not work, when calling setZero() from the base class constructor, and the reason is that derived class has not been constructed yet.
What you need is to initialize each class when its constructed, and that should happen in there respective constructors, and that is what we do in the above code.
Base class constructor will call its own setZero, derived class constructor will call its own setZero.
And you will continue to do the same thing, if you derive any further class from Derived class.

Call overload function based on child in parent container

I'd like to store a child object in a container of its parent type, and then call a function overload based on the type of child in the container. Is that possible?
#include <vector>
class Parent { public: };
class A : public Parent { public: };
class B : public Parent { public: };
class C : public Parent { public: };
class Hander
{
public:
static void handle(A & a) {}
static void handle(B & b) {}
static void handle(C & c) {}
};
int main()
{
A test1;
Hander::handle(test1); // compiles and calls the correct overload
Parent test2 = A();
Hander::handle(test2); // doesn't compile
Parent * test3 = new A();
Hander::handle(*test3); // doesn't compile
Parent children1[] = { A(), B(), C() };
for (int i = 0; i < 3; ++i)
Hander::handle(children1[i]); // doesn't compile
std::vector<Parent*> children2 = { new A(), new B(), new C() };
for (int i = 0; i < 3; ++i)
Hander::handle(*children2[i]); // doesn't compile
}
No, it is not possible.
The function which is called is chosen at compile-time. Lets say you have code like this:
Base &o = getSomeObject();
handle(o);
The compiler doesn't know the real type of o. It only knows that it is some subtype of Base or Base itself. This mean it will search for a function which acceppts objects of type Base.
You could implement a check for the type yourself or use a map to store possible functions:
Base &o = getSomeObject();
functionMap[typeid(o)](o);
But typeid does only work this whay if Base is a polymorphic type. This mean it must have at least one virtual function. This brings us to the next section:
But you could use virtual functions.
Virtual functions are non-static member functions of classes which can be overridden. The right function is resolved at runtime. The following code would output Subt instead of Base:
class Base {
public: virtual std::string f() {return "Base"}
};
class Subt : public Base {
public: virtual std::string f() {return "Subt"}
};
int main() {
Subt s;
Base &b = s;
std::cout << b.f() << std::endl;
}
You can omit virtual in the definition of Subt. The function f() is already defined as virtual in it's base class.
Classes with at least one virtual function (also called polymorphic types) are storing a reference to a virtual function table (also called vtable). This table is used to get the right function at runtime.
The problem in your question could be solved like this:
class Parent {
public:
virtual void handle() = 0;
};
class A : public Parent {
public:
void handle() override { /* do something for instances of A */ }
};
class B : public Parent {
public:
void handle() override { /* do something for instances of B */ }
};
class C : public Parent {
public:
void handle() override { /* do something for instances of C */ }
};
int main()
{
std::vector<std::unique_ptr<Parent>> children = {
std::make_unique<A>(),
std::make_unique<B>(),
std::make_unique<C>()};
for (const auto &child : children)
child->handle();
}
Note about compatibility: The keywords auto and override are only available in C++11 and above. The range-based for loop and std::unique_ptr is also available since C++11. The function std::make_unique is available since C++14. But virtual function can be used with older versions, too.
Another hint:
Polymorphism does only work with references and pointers. The following would call Base::f() and not Subt::f():
Subt s;
Base b = s;
std::cout << b.f() << std::endl;
In this example b will just contain a object of type Base instead of Subt. The object is just created at Base b = s;. It may copy some information from s but it isn't s anymore. It is a new object of type Base.

Template class derived from nontemplate class: access to derived class' generic variable

SOLVED!
I want to create an array of different typed objects using templates.
Therefore I have a non-template class (Base), and a derived template class from Base class.
What I want to know is how can i access to derived class' generic value (T val)?
class Base{
public:
// a function returns T val, it will be implemented in Derived class
// EDIT : virtual function here
};
template<class T>
class Derived: public Base {
public:
T val;
Derived(T x) {
val = x;
}
// implementation.. it returns val
// EDIT : Implementation of virtual function
};
Solution: dynamic_cast, Note that Base class should have at least one virtual function.
Base *p[2];
p[0] = new Derived<int>(24);
p[1] = new Derived<double>(82.56);
int a = dynamic_cast<Derived<int>*>(p[0])->val; // casts p[0] to Derived<int>*
double b = dynamic_cast<Derived<double>*>(p[1])->val; // casts p[1] to Derived<double>*
cout << a << endl;
cout << b << endl;
Last time i checked, You cannot acess derived class members from a base class(non virtual).
You could modify your code this way since you are using templates.The type and value are passed to base class at construction and you can then use it.
template<typename T>
class Base {
T ini;
public:
Base(T arg){ini = arg;}
T ret(){return ini;}
};
template<class T>
class Derived: public Base<T> {
public:
T val;
Derived(T x) : Base<T>(x) {
//Base(x);
val = x;
}
// implementation.. it returns val
};
You can then instantiate it as usual and use it.
Derived<int> e(5);
e.ret();
It look like you want CRTP
The idea is to access the derived class members inside the base class. Note that you won't be able to contain an heterogeneous list of them.
template<typename D>
struct Base {
void doThings() {
// access the derived class getT function
auto var = static_cast<D&>(*this).getT();
cout << var << endl;
}
};
template<typename T>
struct Derived : Base<Derived> {
T getT() {
return myT;
}
private:
T myT;
};

Override pointer-to-member-function

I have these two classes:
class A {
public:
A() { m_ptr = NULL; }
void (*m_ptr)();
void a() { if (m_ptr) m_ptr(); }
};
class B : public A {
public:
B() { m_ptr = b; }
void b() {
std::cout << "B::b() is called" << std::endl;
}
};
And I want to use them like this:
B b;
b.a();
and get the following to be called B::b().
Of course this is not being compiled as B::b is not of type void(*)().
How can I make it work?
UPDATE. To whom who asks "why?" and "what for?".
The class A is a very basic class which has many successors in production code. The class B is 6-th successor and I want to extend A (the most convinient place) to call there one more method (from B) which can be present and may be not in another successors af A and B.
A virtual method with empty body can be employed for that but it is ugly and I want to avoid it. Abstract method even more so (because of existing derived successors code).
I don't want to use external function of type void (*)() to not loose access to internal data of all hierarchy.
You can't make it work as your classes are defined now.
Calling a non-static member function of another class requires an instance of that class. You either need to store a reference to the object that owns the member function when storing the function pointer, or pass a reference to the object when you make the call to A::a.
You also need to declare m_ptr with the type void (B::*)(), which is pointer to member of B that is a function taking no parameters and returning void.
Look at this example:
class A {
public:
A() { m_ptr = nullptr; }
void a(B& b) { if (m_ptr) (b.*m_ptr)(); } // Now takes reference to B object.
void (B::*m_ptr)(); // Pointer to member function of B.
};
class B : public A {
public:
B() { m_ptr = &B::b; } // Adress of qualified function.
void b() {
std::cout << "B::b() is called" << std::endl;
}
};
Now we can call B::b like this:
B b;
b.a(b); // Pass reference to b when calling.
Your use of inheritence in this way is confusing as it implies that the real problem you are trying to solve is to invoka a member of a derived class through the base class. This is usually accomplished using a simple virtual function like this:
class A {
public:
virtual ~A() {}
void a() const { b(); } // Call b.
private:
virtual void b() const {}
};
class B : public A {
public:
virtual void b() const override { // C++11 override specifier (optional).
std::cout << "B::b() is called" << std::endl;
}
};
And used like this:
B b;
b.a(); // B::b is called.
Well, probably not the purpose of this exercise, but you can simply declare static void b() if you want to make it work.
Another option is to declare friend void b(), but then the "B::b() is called" printout would be stating a wrong fact.
I would suggest using CRTP since you want to avoid virtual mechanism. Note, however, your code might require some design changes to accommodate this pattern. But it does provide type safety and has no run-time overhead. Hope it helps.
Code on ideone.com:
#include <iostream>
#include <type_traits>
namespace so {
class B;
template<typename T>
class A {
public:
template<typename U = T, typename = typename std::enable_if<std::is_same<U, B>::value>::type>
void foo_A() {
std::cout << "foo_A : ";
static_cast<U *>(this)->foo_B();
}
};
class B: public A<B> {
public:
void foo_B() {
std::cout << "foo_B" << std::endl;
}
};
class C: public A<C> {
public:
void foo_C() {
std::cout << "foo_C" << std::endl;
}
};
} // namespace so
int main() {
so::B b_;
so::C c_;
b_.foo_A();
b_.foo_B();
//c_.foo_A(); Compile error: A<C>::foo_A() does not exist!
c_.foo_C();
return (0);
}
Program output:
foo_A : foo_B
foo_B
foo_C