【问题标题】:Understanding polymorphism in C++了解 C++ 中的多态性
【发布时间】:2015-11-10 18:55:49
【问题描述】:

我正在尝试使用这个简单的示例来理解 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.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;
}

一切都是在 VS 2010 中使用 Win7 OS(64 位)编译的。

  1. 作业是:

    PolyMorphVector[i]=new Derived;
    

    被认为是好的做法?

  2. 虽然我为 PolyMorphVector 的每个元素分配了 Derived 类,但为什么我必须显式进行动态转换?

【问题讨论】:

  • getDerivedVar 未在基类中声明。要成为多态方法,应在 Base 类中将方法声明为 virtual
  • 哦,回到我第一次学习的那些日子,我会感到非常沮丧,我的大脑会完全停止工作。
  • 想一想……这仍然会发生:p
  • 多态(C++ 面向对象的种类,还有其他种类)是通过基类指针或引用在派生对象中调用虚函数。不多也不少。 dynamic_cast&lt;Derived*&gt;(pBase) 几乎与多态性相反。

标签: c++ polymorphism


【解决方案1】:

(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();

【讨论】:

  • 是的,但是 PolyMorphVector 的每个元素实际上都持有 Derived 而不是 Base。
  • @BennyK 是正确的。嗯,有点。该向量仅包含pointers。实际指向的内容可能不同
【解决方案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 的析构函数(尽管在此示例中,它什么也不做)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多