具有新数据成员的多态性 [英] Polymorphism with new data members

查看:96
本文介绍了具有新数据成员的多态性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想写一个函数,它可以使用多态来初始化和返回不同类的对象。我也希望这些类有不同的数据成员,可以通过虚函数调用。我下面写的可能工作。你能检查我在那里有一些未定义的行为吗?谢谢!我担心的一件事是,当我调用删除多点的最后,它不会释放CRectangle特有的数据成员scale。如果我的代码不工作是有办法使它工作吗?

I would like to write a function that can initialize and return objects of different classes using polymorphism. I also would like these classes to have different data members which may be called through the virtual function. What I wrote below might work. Could you check if I have some undefined behavior in there? Thank you! One thing I am worried about is that when I call "delete polypoint" at the end it will not free the data member "scale" that is unique to "CRectangle". If my code doesn't work is there a way to make it work?

class CPolygon {
  protected:
    int width, height;
  public:
    void set_values (int a, int b)
      { width=a; height=b; }
    virtual int area ()
      { return (0); }
  };

class CRectangle: public CPolygon {
  public:
    int scale;
    int area ()
      { return (width * height * scale ); }
  };

CPolygon *polytestinner()
{
    CPolygon *polypoint = 0;

    int consoleinput = 2;
    if (consoleinput>1)
    {
        CRectangle *rectpoint = new CRectangle();
        rectpoint->scale = 4;
        polypoint = rectpoint;
    }
    polypoint->set_values(3,4);
    return polypoint;
}

void polytest()
{
    CPolygon *polypoint = polytestinner();
    gstd::print<int>(polypoint->area());    
    delete polypoint;
}

int main()
{
    polytest();
    return 0;
}

谢谢!

推荐答案

我不得不指出Andrei Alexandrescu的对象工厂架构。它允许您的架构增长,而不必在每次创建一个具体类型时修改工厂。它基于回调寄存器,并且实际上在一些库中实现为通用组件。代码如下。

I feel compelled to point out Andrei Alexandrescu's object factory architecture. It allows your architecture to grow without having to modify the factory every time you create a concrete type. It is based on a "callback register", and it is actually implemented as a generic component in some libraries. The code is below.

实时代码示例< a>

Live Code Example

#include<map>
#include<iostream>
#include<stdexcept>

// your typical base class
class Shape {
 public:
  virtual void Draw() const = 0;
  // virtual destructor allows concrete types to implement their own
  // destrucion mechanisms
  virtual ~Shape() {} 
};

// this factory architecture was suggested by Andrei Alexandrescu in
// his book "Modern C++ Design" --- read it to get the full
// explanation (and a more generic implementation); this is just an
// example
class ShapeFactory {
 public:
  // this typedef allows to "name" arbitrary functions which take no
  // arguments and return a pointer to a Shape instance
  typedef Shape* (*CreateShapeCallback)();

  Shape* CreateShape(int ShapeId) {
    // try to find the callback corresponding to the given shape id;
    // if no shape id found, throw exception
    CallbackMap::const_iterator it = m_callbacks.find(ShapeId);
    if(it == m_callbacks.end()) {
      throw std::runtime_error("unknown shape id");
    } else {
      // create the instance using the creator callback
      return (it->second)();
    }    
  }

  bool RegisterShape(int ShapeId, CreateShapeCallback Creator) {
    // returns true if shape was registered; false if it had already
    // been registered
    return m_callbacks.insert(CallbackMap::value_type(ShapeId, Creator)).second;
  }

  bool UnRegisterShape(int ShapeId) {
    // returns true if shape was unregistered, false if it was not
    // registered in the first place
    return m_callbacks.erase(ShapeId) == 1;
  }

 private:
  // the typedef simplifies the implementation
  typedef std::map<int, CreateShapeCallback> CallbackMap;
  // the callbacks are stored in a map int->callback (see typedef
  // above)
  CallbackMap m_callbacks;
};


// create some concrete shapes... you would do this in other CPP files
class Line : public Shape {
 public:
  void Draw() const {
    std::cout<<"Drawing a line"<<std::endl;
  }
};

// another concrete shape...
class Circle : public Shape {
 public:
  void Draw() const {
    std::cout<<"Drawing a circle"<<std::endl;
  }
};
// ... other concrete shapes...

enum ShapeIds {LINE=1, CIRCLE, COUNT};
Shape* CreateLine() { return new Line; }
Shape* CreateCircle() { return new Circle; }


int main() {
  // suppose this is the "singleton" instance for the ShapeFactory
  // (this is an example! Singletons are not implemented like this!)  
  ShapeFactory *factory = new ShapeFactory;
  factory->RegisterShape(ShapeIds::LINE, CreateLine);
  factory->RegisterShape(ShapeIds::CIRCLE, CreateCircle);

  Shape* s1 = factory->CreateShape(ShapeIds::CIRCLE);
  Shape* s2 = factory->CreateShape(ShapeIds::LINE);
  s1->Draw();
  s2->Draw();
  // will throw an error
  try {
    Shape *s3 = factory->CreateShape(-1);
    s3->Draw();    
  } catch(const std::exception& e) {
    std::cout<<"caught exception: "<<e.what()<<std::endl;    
  }
  return 0;
}

这篇关于具有新数据成员的多态性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆