inheritance and polymorphism for class and its member at the same time (shared_ptr, C++11

By : Denis
Source: Stackoverflow.com
Question!

I am playing around with the following structure of classes which use std::shared_ptr (C++11):

#include <string>
#include <iostream>
#include <vector>
#include <memory>

//class Member is given by a 3rd party library, CAN'T modify its structure!
class Member {//no instance of this class allowed
   public:
     Member() {};//should never be called
     virtual ~Member() = 0;//pure virtual distructor;
     virtual void foo() {
       std::cout<<"Member"<<std::endl;
     }
};
Member::~Member() {} //need to define destructor because of child classes 

class ChildMember : public Member {
  public:
     ChildMember() {};
     virtual void foo() {
         std::cout<<"Child Member"<<std::endl;
     }

     virtual void foo2() {
        std::cout<<"unique foo in child"<<std::endl;
     }
};

class Base {
   public:
     Base() {};

   virtual
   std::shared_ptr< Member >
   get_var() {return var;}

   virtual void 
   set_var ( std::shared_ptr< Member > v) { var = v;}

   std::shared_ptr< Member > var;
};


class ChildBase : public Base {
  public:
     ChildBase() {
        //var = std::make_shared<ChildMember>();
     };

  virtual
  std::shared_ptr< ChildMember >
  get_var() {return var;} //(2) : try to comment

  virtual void 
  set_var ( std::shared_ptr< ChildMember > v) { var = v;}

  std::shared_ptr< ChildMember > var;
};

void func(std::shared_ptr<Base> b) {
    b->get_var()->foo();// process input using polymorphism
}

int main() 
{
    std::shared_ptr<ChildBase> cb( std::make_shared<ChildBase>());
    cb->set_var (std::make_shared<ChildMember>() );
    cb->get_var()->foo2();//(3) want to use unique functions of ChildBase;
    cb->var->foo2();      //can access directly as well;
    //cb->var = std::make_shared<ChildMember>();
    func(cb);
}

What i try to do is design two classes (Base and ChildBase) where each one has its own member Member / ChildMember. After full usage of ChildBase object and its member object of type ChildMember, i pass it to a function func which receives Base and should, using polymorphism call the proper foo of a member var.

Problems: (1) In the variant in the above, compiler complains that:

 overriding 'virtual std::shared_ptr<Member> Base::get_var()'
     get_var() {return var;}`

(2) If i comment-out ChildBase implementation of get_var, this function is treated as Base and thus returns a pointer to Member which does not have foo2.

(3) I can also comment out cb->get_var()->foo2() . The whole things compiles, but it seems it does not call ChildMember::foo() as there is no output Child Member;

Something is (hopefully) slightly messed up but i don't see what. Could you guys please help to correct it?

EDIT1:

based on Abhijit Kadam answer, the following code fully compiles:

#include <string>
#include <iostream>
#include <vector>
#include <memory>

class Member {//no instance of this class allowed
   public:
     Member() {};
     virtual ~Member() = 0;//pure virtual distructor;
     virtual void foo() {
       std::cout<<"Member"<<std::endl;
     }
};
Member::~Member() {} //need to define destructor for child classes 

class ChildMember : public Member {
  public:
     ChildMember() {};
     virtual void foo() {
        std::cout<<"Child Member"<<std::endl;
     }

     void foo2() {
        std::cout<<"unique foo in child"<<std::endl;
     }
};

class Base {
   public:
     Base() {};

     std::shared_ptr< Member >
     get_var() {return var;}

     void set_var ( std::shared_ptr< Member > v) { var = v;}

     std::shared_ptr< Member > var;
};


class ChildBase : public Base {
  public:
     ChildBase() {
       //var = std::make_shared<ChildMember>();
     };  

     std::shared_ptr< ChildMember > var;
};

void func(std::shared_ptr<Base> b) {
    b->get_var()->foo();// process input using polymorphism
}

 void func_vec( std::vector< 
              std::shared_ptr<Base>
           > vec) {
     for (unsigned int i=0;i<vec.size();i++)
          vec[i]->get_var()->foo();
  }

int main() 
{
   std::shared_ptr<ChildBase> cb( std::make_shared<ChildBase>());
   cb->set_var (std::make_shared<ChildMember>() );

   func(cb);

   std::vector< std::shared_ptr<Base>> vec;
   vec.push_back(cb);
   func_vec(vec);

   cb->var->foo2();

   /*std::shared_ptr<ChildMember> ptr(std::dynamic_pointer_cast<ChildMember>(cb->get_var()) );
   if (ptr) {
      ptr->foo2();
   } */
}

EDIT2 added an answer below.

By : Denis


Answers
As the return types of overriding functions cannot differ I would have use dynamic cast to implement the solution. Hence no need to have virtual functions for `get_var and set_var'. Also no need for foo2 to be virtual unless the class would be further derived by some other class.

int main() 
{
    std::shared_ptr<ChildBase> cb( std::make_shared<ChildBase>());
    cb->set_var (std::make_shared<ChildMember>() );

    shared_ptr<ChildMember> ptr(dynamic_pointer_cast<ChildMember>(cb->get_var()) );
    if (ptr) {
        ptr->foo2();
    } 
}

class Member {//no instance of this class allowed
   public:
     Member() {};
     virtual ~Member() = 0;//pure virtual distructor;
     virtual void foo() {
       std::cout<<"Member"<<std::endl;
     }
};
Member::~Member() {} //need to define destructor for child classes 

class ChildMember : public Member {
  public:
     ChildMember() {};
     virtual void foo() {
         std::cout<<"Child Member"<<std::endl;
     }

     void foo2() {
        std::cout<<"unique foo in child"<<std::endl;
     }
};

class Base {
   public:
     Base() {};

   std::shared_ptr< Member >
   get_var() {return var;}

   void set_var ( std::shared_ptr< Member > v) { var = v;}

   std::shared_ptr< Member > var;
};


class ChildBase : public Base {
  public:
     ChildBase() {
        //var = std::make_shared<ChildMember>();
     };  

  std::shared_ptr< ChildMember > var;
};

void func(std::shared_ptr<Base> b) {
    b->get_var()->foo();// process input using polymorphism
}


It's wrong overriding. n3337 10.3/7

The return type of an overriding function shall be either identical to the return type of the overridden function or covariant with the classes of the functions. If a function D::f overrides a function B::f, the return types of the functions are covariant if they satisfy the following criteria:

— both are pointers to classes, both are lvalue references to classes, or both are rvalue references to classes

— the class in the return type of B::f is the same class as the class in the return type of D::f, or is an unambiguous and accessible direct or indirect base class of the class in the return type of D::f

— both pointers or references have the same cv-qualification and the class type in the return type of D::f has the same cv-qualification as or less cv-qualification than the class type in the return type of B::f.

All conditions fails in your case. You can use raw-pointers, or references for this, something like http://liveworkspace.org/code/4eQWBI$1 But I think you should rewrite your interface and not use foo2, if it's not virtual.

By : ForEveR


To solve your problem, see this modified and annotated version of your code:

#include <string>
#include <iostream>
#include <vector>
#include <memory>

class Member {//no instance of this class allowed
public:
    Member() {};
    virtual ~Member() = 0;//pure virtual distructor;
    virtual void foo() {
        std::cout<<"Member"<<std::endl;
    }
};
Member::~Member() {} //need to define destructor for child classes 

class ChildMember : public Member {
public:
    ChildMember() {};
    virtual void foo() {
        std::cout<<"Child Member"<<std::endl;
    }

    virtual void foo2() {
        std::cout<<"unique foo in child"<<std::endl;
    }
};

class Base {
public:
    Base() {};

    // maybe you should have a virtual dtor here
    virtual ~Base();

    // note: NOT virtual
    std::shared_ptr< Member >
    get_var() {return var;}

    // also NOT virtual
    void set_var ( std::shared_ptr< Member > v) { var = v;}

    std::shared_ptr< Member > var;
};


class ChildBase : public Base {
public:
    ChildBase() {
        //var = std::make_shared<ChildMember>();
    };

    // non-virtual version which casts var to the correct type
    std::shared_ptr< ChildMember >
    get_var() {return std::dynamic_pointer_cast<ChildMember>(var);}

    // note: no var here, use the one from Base
};

void func(std::shared_ptr<Base> b) {
    b->get_var()->foo();// process input using polymorphism
}

int main() 
{
    std::shared_ptr<ChildBase> cb( std::make_shared<ChildBase>());
    cb->set_var (std::make_shared<ChildMember>() );
    cb->get_var()->foo2();//(3) want to use unique functions of ChildBase;

    // This can't work:
    //cb->var->foo2();      //can access directly as well;

    //cb->var = std::make_shared<ChildMember>();
    func(cb);
}


This video can help you solving your question :)
By: admin