类及其成员的继承和多态性(shared_ptr,C++11)

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

本文关键字:shared ptr C++11 多态性 成员 继承      更新时间:2023-10-16

我正在处理以下使用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);
}

我尝试设计两个类(BaseChildBase(,其中每个类都有自己的成员Member/ChildMember。在完全使用ChildBase对象及其类型为ChildMember的成员对象后,我将其传递给接收Base的函数func,并且应该使用多态性调用成员var的适当foo

问题:(1(在上面的变体中,编译器抱怨道:

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

(2(如果我注释掉get_varChildBase实现,则此函数被视为Base,并因此返回指向没有foo2Member的指针。

(3(我也可以评论cb->get_var()->foo2()。所有的东西都编译了,但似乎没有调用ChildMember::foo(),因为没有输出Child Member

有些事情(希望(有点乱,但我不知道是什么。你们能帮忙纠正一下吗?

EDIT1

基于Abhijit Kadam的回答,以下代码完全编译:

#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();
   } */
}

编辑2在下面添加了一个答案。

由于重写函数的返回类型不能不同,我将使用动态转换来实现该解决方案。因此,"get_var和set_var"不需要具有虚拟函数。此外,foo2不需要是虚拟的,除非该类将由其他类进一步派生。

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
}
virtual
std::shared_ptr< Member >
get_var() {return var;}
virtual
std::shared_ptr< ChildMember >
get_var() {return var;} //(2) : try to comment

压倒一切是错误的。n3337 10.3/7

重写函数的返回类型应与重写的返回类型相同函数或协变函数的类。如果函数D::f覆盖函数B::f,则如果函数的返回类型满足以下条件,则它们是协变的:

--两者都是指向类的指针,都是对类的左值引用,或者都是对的右值引用类

--返回类型B::f中的类与返回类型D::f的类是同一类,或者是D::f 返回类型中类的明确且可访问的直接或间接基类

--两个指针或引用在D::f的返回类型中具有相同的cv限定和类类型具有与B::f的返回类型中的类类型相同或更少的cv资格

在您的情况下,所有条件都会失败。您可以使用原始指针或引用,例如http://liveworkspace.org/code/4eQWBI1美元但我认为你应该重写你的接口,不要使用foo2,如果它不是虚拟的。

要解决您的问题,请参阅代码的修改和注释版本:

#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);
}

shared_ptr而不是指针,因此协方差不适用。

通常,我对协方差的使用持怀疑态度。我通常会发现派生类不更改更干净返回类型,并在需要时提供一个新函数返回指向派生函数的指针。在你的情况下,我想说这是至关重要的,因为你实际上有两个指针(最终可能指向不同的对象(。

一段时间后,我认为以下代码可能是一个很好的解决方案:
#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 ChildMember1 : public Member {
  public:
     ChildMember1() {};
     virtual void foo() {
        std::cout<<"Child Member 1"<<std::endl;
     }
     void foo1() {
        std::cout<<"unique foo in child 1"<<std::endl;
     }
};
class ChildMember2 : public Member {
  public:
     ChildMember2() {};
     virtual void foo() {
        std::cout<<"Child Member 2"<<std::endl;
     }
};
class ChildChildMember2 : public ChildMember2 {
   public:
      ChildChildMember2() {};
      virtual void foo() {
         std::cout<<"Child-Child Member 2"<<std::endl;
      }
};
class Base {
   public:
     Base() {};
     virtual
     ~Base() {};
     virtual
     std::shared_ptr< Member >
     get_var() = 0; //purely abstract class
};
class ChildBase1 : public Base {
  public:
     ChildBase1() {
       var = std::make_shared<ChildMember1>();
     };
     virtual
     std::shared_ptr< Member >
     get_var() {return var;}
     std::shared_ptr< ChildMember1 > var;
};
class ChildChildBase : public ChildBase1 {
   public:
      ChildChildBase() {
         var2 = std::make_shared< ChildChildMember2>();
      }
   virtual
   std::shared_ptr< Member >
   get_var() { return var2; }
   std::shared_ptr< ChildChildMember2 > var2;
};

class ChildBase2 : public Base {
  public:
     ChildBase2() {
       var = std::make_shared<ChildMember2>();
     };  
     virtual
     std::shared_ptr< Member >
     get_var() {return var;}
     std::shared_ptr< ChildMember2 > var;
};
void func(std::shared_ptr<Base> b) {
    b->get_var()->foo();// process input using polymorphism
}
int main() 
{
   std::shared_ptr<ChildBase1> cb1( std::make_shared<ChildBase1>());
   cb1->var->foo1();
   func(cb1);
   std::shared_ptr<ChildBase2> cb2( std::make_shared<ChildBase2>());
   func(cb2);
   std::shared_ptr<ChildChildBase> ccb( std::make_shared<ChildChildBase>());
   func(ccb);
}

我认为它实现了我所追求的,没有并行继承或动态铸造。它还有超过1级的继承。

输出为:

unique foo in child 1
Child Member 1
Child Member 2
Child-Child Member 2