首页 > 解决方案 > 将对象声明为抽象类

问题描述

编辑最初发布的这个问题是我所拥有的简化版本,因此不包含导致错误的问题。我已经更新为更像我的问题,并且会发布答案以防其他人遇到类似问题。

在 C++ 中是否可以将对象声明为抽象类,然后将其实例化为派生类?

以这个修改版本的示例代码为例,从https://www.tutorialspoint.com/cplusplus/cpp_interfaces.htm获得

class Shape {
   public:
      // pure virtual function providing interface framework.
      virtual int getArea() = 0;
      virtual int getNumOfSides() = 0;
      void setWidth(int w) {
         width = w;
      }
   
      void setHeight(int h) {
         height = h;
      }
   
   protected:
      int width;
      int height;
};
 
// Derived classes
class Rectangle: public Shape {
   public:
      int getArea() { 
         return (width * height); 
      }
};

class Triangle: public Shape {
   public:
      int getArea() { 
         return (width * height)/2; 
      }
};
 
int main(void) {
   Rectangle Rect;
   Triangle  Tri;
 
   Rect.setWidth(5);
   Rect.setHeight(7);
   
   // Print the area of the object.
   cout << "Total Rectangle area: " << Rect.getArea() << endl;

   Tri.setWidth(5);
   Tri.setHeight(7);
   
   // Print the area of the object.
   cout << "Total Triangle area: " << Tri.getArea() << endl; 

   return 0;
}

但是,如果我们在编译时不知道 Shape 的类型,是否可以执行以下操作:

Shape *shape;

if (userInput == 'R') {
   shape = new Rectangle();
} else if (userInput == 'T') {
   shape = new Triangle();
}

// etc.

... 可以在 C# 中完成吗?

我已经尝试过了,但得到了错误:

错误:抽象类类型“矩形”的无效新表达式

这是在 QT 内。

标签: c++qtoopabstract-class

解决方案


在 C++ 中是否可以将对象声明为抽象类,然后将其实例化为派生类?

你不能声明一个对象,不。抽象类不能被实例化。但是,您可以声明一个指向实现抽象类的对象的引用/指针,是的。例如:

Shape *shape;

if (userInput == 'R') {
   shape = new Rectangle();
} else if (userInput == 'T') {
   shape = new Triangle();
}

// etc.

delete shape;

在 C++11 及更高版本中,当指针超出范围时,您可以使用std::unique_ptrorstd::shared_ptr自动调用,例如:delete

std::unique_ptr<Shape> shape;

if (userInput == 'R') {
   shape.reset(new Rectangle);
   // or: shape = std::unique_ptr<Shape>(new Rectangle);
   // or: shape = std::make_unique<Rectangle>(); // C++14 and later only
} else if (userInput == 'T') {
   shape.reset(new Triangle);
   // or: shape = std::unique_ptr<Shape>(new Triangle);
   // or: shape = std::make_unique<Triangle>(); // C++14 and later only
}

// etc.
std::shared_ptr<Shape> shape;

if (userInput == 'R') {
   shape.reset(new Rectangle);
   // or: shape = std::make_shared<Rectangle>();
} else if (userInput == 'T') {
   shape.reset(new Triangle);
   // or: shape = std::make_shared<Triangle>();
}

// etc.

无论哪种方式,只要确保它Shape有一个virtual析构函数,以便在通过指针delete'ing 派生对象时调用正确的派生析构函数:Shape*

class Shape {
   public:
      virtual ~Shape() {}
   // ...
}; 

推荐阅读