用户如何选择在C+&#x2B中的抽象类成员变量的实现。

发布于 2025-02-07 18:08:25 字数 1689 浏览 2 评论 0原文

我希望我的类“ Shapeholder”的用户能够将“ Shape Shape”成员变量设置为具有相同界面(INT W/H,GetArea()等)的任何类。因此,我相信我通过将函数设置为Virtual(?),并添加了派生的类,以充当形状的各种实现,将基类作为抽象类。

但是,此当前代码在定义了形状形状成员变量的情况下引发了一个错误,称我“无法声明字段'Shapeholder :: Shape'为抽象类型'Shape'”。

在完美的世界中,我希望用户能够交出与他们想要由形状成员变量代表的类相对应的枚举。有办法这样做吗?

是否有比基础更好的方法:我要在这里创建的派生类界面?

我有以下示例程序来说明我的问题:

#include <iostream>
#include <string>

using namespace std;

typedef int shape_type;
enum {SQUARE, TRIANGLE, REGTANGLE};

// Base class
class Shape {
   public:
      Shape(int h, int w){
        height = h;
        width = w;
      };
      virtual int getArea() = 0;
      //int getArea(){return -999;};
   
   private:
      int width;
      int height;
};
 
// Derived classes
class Rectangle: public Shape {
  public:
    Rectangle(int h, int w) : Shape(h, w){
      height = h;
      width = w;
    };
    int getArea() { 
        return (width * height); 
    }
  private:
      int height;
      int width;
};

class Triangle: public Shape {
  public:
    Triangle(int h, int w) : Shape(h, w){
      height = h;
      width = w;
    };
    int getArea() { 
        return (width * height)/2; 
    }
  private:
      int height;
      int width;
};

// Main Class
class ShapeHolder {
  public:
    ShapeHolder(int ver, string s, shape_type st):
      dummyInt(ver), dummyString(s), shape(ver, ver){};
    void printStuff(){
        cout << shape.getArea() << endl;
    }
  private:           
    int dummyInt;
    string dummyString;
    // this type should be dependent on shape_type
    Shape shape;

};

int main() {
  ShapeHolder sh(10, "test", TRIANGLE);
  sh.printStuff();
  return 0;
}

I want users of my class "ShapeHolder" to be able to set the "Shape shape" member variable to be any class with the same interface (int w/h, getArea(), etc). Therefore, I believe I made the base class an abstract class by setting a function to virtual (?), and added derived classes to act as the various implementations of shape.

However, this current code throws an error where the Shape shape member variable is defined, saying that I "cannot declare field 'ShapeHolder::shape' to be of abstract type 'Shape'".

In the perfect world, I would love the user to be able to hand in the enum corresponding to the class they want to be represented by the Shape member variable. Is there a way to do this?

Is there a better method all together than the base:derived class interface I am trying to create here?

I have the following example program to illustrate my question:

#include <iostream>
#include <string>

using namespace std;

typedef int shape_type;
enum {SQUARE, TRIANGLE, REGTANGLE};

// Base class
class Shape {
   public:
      Shape(int h, int w){
        height = h;
        width = w;
      };
      virtual int getArea() = 0;
      //int getArea(){return -999;};
   
   private:
      int width;
      int height;
};
 
// Derived classes
class Rectangle: public Shape {
  public:
    Rectangle(int h, int w) : Shape(h, w){
      height = h;
      width = w;
    };
    int getArea() { 
        return (width * height); 
    }
  private:
      int height;
      int width;
};

class Triangle: public Shape {
  public:
    Triangle(int h, int w) : Shape(h, w){
      height = h;
      width = w;
    };
    int getArea() { 
        return (width * height)/2; 
    }
  private:
      int height;
      int width;
};

// Main Class
class ShapeHolder {
  public:
    ShapeHolder(int ver, string s, shape_type st):
      dummyInt(ver), dummyString(s), shape(ver, ver){};
    void printStuff(){
        cout << shape.getArea() << endl;
    }
  private:           
    int dummyInt;
    string dummyString;
    // this type should be dependent on shape_type
    Shape shape;

};

int main() {
  ShapeHolder sh(10, "test", TRIANGLE);
  sh.printStuff();
  return 0;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

荒岛晴空 2025-02-14 18:08:25

您的类Shape是一个抽象类,缺少定义的纯虚拟函数。

通过将Shape Shape转换为Shapeholder类,将其修复到指针中,它允许使用任何派生的shape类。

另外,标记width&amp; height base类内部的变量受保护允许派生类访问它们。

Your class Shape is an abstract class and lacks definition's for it's pure virtual function.

Fix this by converting Shape shape inside your ShapeHolder class to a pointer instead, whichs allows any derived Shape class to be used.

Also, marking the width & height variable's inside the base class protected allows derived classes to access them.

冧九 2025-02-14 18:08:25

在课堂中声明成员函数 pure virtual ,您无法实例化该类的对象。

因此,在您的Shapeholder类中,将Shape变量声明为Shape Shape Shape将导致编译错误。

error: cannot declare field ‘ShapeHolder::shape’ to be of abstract type ‘Shape’
   65 |     Shape shape;
      |           ^~~~~

您不能直接创建抽象类的变量,但是可以保留指针或对抽象类的引用。

抽象类就像抽象类和派生类之间的接口/合同。从抽象类得出的任何类都必须实现此接口/合同。

如下更改您的基类:

class Shape {
public:
    Shape(int h, int w) : height{h}, width{w} {}
    virtual int getArea() = 0;

// protected instead of private so that derived classes can access it
protected:
    int height;
    int width;
};
class ShapeHolder {
public:
    ShapeHolder(int h, int w, string s, shape_type st): dummyString(s) {
        // Based on st, create either Triangle or Rectangle
        switch (st)
        {
        case TRIANGLE:
            shape = std::make_unique<Triangle>(h, w);
        break;
        case REGTANGLE:
            shape = std::make_unique<Rectangle>(h, w);
        break;
        }
    };

    void printStuff(){
        cout << shape->getArea() << endl;
    }

private:
    string dummyString;
    std::unique_ptr<Shape> shape;  // pointer to keep track of shape
};

在您的中,三角形矩形类无需具有widthheight> height accope 变量,他们将可以访问基类widthheight。因此,

class Rectangle: public Shape {
public:
    Rectangle(int h, int w) : Shape(h, w) {}
    int getArea() override { return (width * height); }
};

class Triangle: public Shape {
public:
    Triangle(int h, int w) : Shape(h, w) {}
    int getArea() override { return (width * height)/2; }
};

Main函数中:

int main() {
  ShapeHolder shape1(10, 20, "tri", TRIANGLE);
  shape1.printStuff();

  ShapeHolder shape2(5, 8, "rect", REGTANGLE);
  shape2.printStuff();
}

输出:

100
40

In a class once you declare a member function pure virtual, you can't instantiation an object of that class.

So in your ShapeHolder class, declaring the shape variable as Shape shape will cause a compilation error.

error: cannot declare field ‘ShapeHolder::shape’ to be of abstract type ‘Shape’
   65 |     Shape shape;
      |           ^~~~~

You can't directly create a variable of abstract class but you can keep a pointer or reference to abstract class.

Abstract class is like an interface/contract between abstract class and derived class. Any class which is derived from abstract class must implement this interface/contract.

Change your base class as follows:

class Shape {
public:
    Shape(int h, int w) : height{h}, width{w} {}
    virtual int getArea() = 0;

// protected instead of private so that derived classes can access it
protected:
    int height;
    int width;
};
class ShapeHolder {
public:
    ShapeHolder(int h, int w, string s, shape_type st): dummyString(s) {
        // Based on st, create either Triangle or Rectangle
        switch (st)
        {
        case TRIANGLE:
            shape = std::make_unique<Triangle>(h, w);
        break;
        case REGTANGLE:
            shape = std::make_unique<Rectangle>(h, w);
        break;
        }
    };

    void printStuff(){
        cout << shape->getArea() << endl;
    }

private:
    string dummyString;
    std::unique_ptr<Shape> shape;  // pointer to keep track of shape
};

In your Triangle and Rectangle classes no need to have width and height variables, they will have access to base class width and height. So

class Rectangle: public Shape {
public:
    Rectangle(int h, int w) : Shape(h, w) {}
    int getArea() override { return (width * height); }
};

class Triangle: public Shape {
public:
    Triangle(int h, int w) : Shape(h, w) {}
    int getArea() override { return (width * height)/2; }
};

In the main function:

int main() {
  ShapeHolder shape1(10, 20, "tri", TRIANGLE);
  shape1.printStuff();

  ShapeHolder shape2(5, 8, "rect", REGTANGLE);
  shape2.printStuff();
}

Output:

100
40
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文