理解C ++中的多态性

时间:2015-11-10 18:55:49

标签: c++ polymorphism

我试图用这个简单的例子来理解C ++中的多态性机制(为了清楚起见,构造函数在hpp文件中明确写出,同样适用于公共成员)

基类:

//Base.hpp
#ifndef _Base_H_
#define _Base_H_
class Base{

    public:

    int BaseVar;

    Base():BaseVar(0){};
    int getBaseVar(){return BaseVar;}
    virtual int DoNothing(){return 0;};

};
#endif   

派生类

//Derived.hpp
#include "Base.hpp"
#ifndef _Derived_H_
#define _Derived_H_

class Derived: public Base{

   public:
   int DerivedVar;

   Derived():Base(),DerivedVar(0){};
   int getDerivedVar(){return DerivedVar;}
};

#endif

Polymorph class

//Polymorph.hpp
#include "Derived.hpp"
#include <vector>
using namespace std;
#ifndef _Polymorph_H_
#define _Polymorph_H_

class Polymorph{

    public:
    vector<Base *> PolyMorphVector;

    Polymorph(int VectorSize):PolyMorphVector(VectorSize)
    {

      for (int i(0);i<VectorSize;i++)
          PolyMorphVector[i]=new Derived;

    }

 };

#endif

主程序

//main.cpp
#include "Polymorph.hpp"

int main()
{
    int i;
    Polymorph *MyPolymorph = new Polymorph(10);
    i=MyPolymorph->PolyMorphVector[0]->getDerivedVar();//copmiler error: "'getDerivedVar' : is not a member of 'Base'" ... Oh, really?
    i=(dynamic_cast<Derived *>(MyPolymorph->PolyMorphVector[0]))->getDerivedVar();//OK!!
    return 0;
}

使用Win7 OS(64位)在VS 2010中编译了Everthing。

  1. 是作业:

    PolyMorphVector[i]=new Derived;
    

    被视为良好做法?

  2. 为什么我必须明确地使用dynamic_cast,尽管我使用Derived类分配了PolyMorphVector的每个元素?

2 个答案:

答案 0 :(得分:4)

(1)作业有效,但在任何地方都没有明确的所有权,你最好用

这样的东西
std::vector<std::unique_ptr<Base>> poly_morph_vector;

然后按

初始化
for (auto& b : poly_morph_vector) {
     b = std::make_unique<Derived>();
}

(2)Base没有该名称的成员函数,因此您得到编译时错误。如果你想要动态发送,你需要像

这样的东西
class Base {
 public:
  virtual int get_var() const { return base_var; }
};

class Derived : public Base {
 public:
  int get_var() const override { return derived_var; }
};

然后你的代码得到变量

auto i = MyPolymorph->poly_morph_vector.front()->get_var();

答案 1 :(得分:2)

您的示例中没有使用任何真正的多态性。多态的概念是可以从基类定义的接口调用派生类提供的函数。特别是,可以使用接口(调用virtual方法)并完全独立地实现(定义派生类),但它可以工作。

struct base
{
    virtual int method1() const = 0;      // pure virtual: has to be overriden
    virtual int method2(int i) const      // defaults to base::method2()
    { return i*x; }
    base(int i) : x(i) {}
    virtual ~base() {}                    // derived can be destroyed from here
    const int x;
};

void print(const base*p)                  // using the interface
{
    std::cout << p->method1() << std::endl;
}

struct derived : base                     // providing an interface
{
    int method1() const override
    { return method2(x); }                // polymorphic call of foo::method2
    derived(int i): base(i), x(i+i) {}
    const int x;
};

struct foo : derived                      // extending the interface again
{
    int method2(int i) const override
    { return i<<2; }
    foo(int i) : derived(2+i);
};

std::vector<unique_ptr<base>> pter;
for(int i=0; i!=10; ++i)
    pter.push_back(make_unique<foo>(i));  // unfortunately make_unique is C++14

for(auto const&p:pter)
    print(p.get());                       // calls foo::method1()

请注意pter的析构函数将调用base::~base()virtual将调用foo的析构函数(尽管在此示例中,它不执行任何操作)。