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

时间:2013-04-01 10:42:35

标签: c++ oop inheritance c++11 polymorphism

我正在使用以下使用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类型的成员对象后,我将其传递给接收func的函数Base,并且应该使用多态性调用成员foo的正确var

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

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

(2) 如果我评论ChildBase get_var的实现,则此函数将被视为Base,从而返回指向Member但没有foo2的指针。

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

EDIT2 在下面添加了答案。

5 个答案:

答案 0 :(得分:1)

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-qualification和类类型 与B :: f的返回类型中的类类型具有相同的cv资格或更少的cv资格。

您的情况下所有条件都失败了。您可以使用原始指针或引用,例如http://liveworkspace.org/code/4eQWBI $ 1 但我认为你应该重写你的界面而不是使用foo2,如果它不是虚拟的。

答案 1 :(得分:1)

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

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

答案 2 :(得分:1)

由于覆盖函数的返回类型不能有所不同,我将使用动态强制转换来实现解决方案。因此,不需要为`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
}

答案 3 :(得分:0)

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

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

答案 4 :(得分:0)

过了一会儿,我虽然以下代码可能是一个很好的解决方案:

#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 lvl的继承。

输出结果为:

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