与新数据成员的多态性

时间:2013-04-12 17:41:14

标签: c++ polymorphism

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

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

谢谢!

3 个答案:

答案 0 :(得分:4)

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

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

答案 1 :(得分:3)

CPolygon需要一个虚拟析构函数:

virtual ~CPolygon() {}

答案 2 :(得分:1)

您的代码中有undefined behavior

  CPolygon *polypoint;
  delete polypoint;

在没有虚拟析构函数时删除base class pointer将导致未定义的行为。

您的CPolygon类和CRectangle类没有析构函数,但在这种情况下编译器会为您生成默认析构函数,但它们是not virtual by default。因此,您至少需要为基类定义virtual destructor,即CPolygon