簡體   English   中英

類及其成員的繼承和多態性(shared_ptr,C ++ 11)

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

我正在研究以下使用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成員對象ChildMember ,我將其傳遞給一個函數func ,該函數接收Base並且應該使用多態性來調用成員var的適當foo

問題: (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 ;

(希望)有點混亂,但我看不到。 你們能幫忙改正嗎?

編輯1

根據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在下面添加了一個答案。

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

—指針或引用都具有相同的cv限定,並且D :: f的返回類型中的類類型具有與b :: f的返回類型中的類類型相同或更少的cv限定。

在您的情況下,所有條件均失敗。 您可以使用原始指針或對此的引用,例如http://liveworkspace.org/code/4eQWBI $ 1。但是我認為您應該重寫您的接口,而不是使用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);
}

由於覆蓋函數的返回類型不能不同,因此我將使用動態強制轉換來實現該解決方案。 因此,不需要為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
}

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM