C++ 只实例化一次派生类是否是错误的OOP?

C++ 只实例化一次派生类是否是错误的OOP?,c++,oop,inheritance,instantiation,C++,Oop,Inheritance,Instantiation,我有一个类结构,它只打算让我的派生类每个只实例化一次。在我看来,这就像糟糕的OOP,因为多个实例是相同的,没有任何用途,所以我应该替换它吗 上下文: 我正在为计算器应用程序建立基础。我有一个操作符类,它继承自。我使用Operator作为一个抽象基类,然后“计算器”包含一个多态容器Operator*,其中包含一个支持的操作实例,因此它只需匹配ID就可以对操作符调用evaluate class Operator { public: virtual int evaluate(int left,

我有一个类结构,它只打算让我的派生类每个只实例化一次。在我看来,这就像糟糕的OOP,因为多个实例是相同的,没有任何用途,所以我应该替换它吗

上下文: 我正在为计算器应用程序建立基础。我有一个
操作符
类,它继承自。我使用
Operator
作为一个抽象基类,然后“计算器”包含一个多态容器
Operator*
,其中包含一个支持的操作实例,因此它只需匹配ID就可以对操作符调用
evaluate

class Operator {
public:
    virtual int evaluate(int left, int right) = 0;

protected:
    const char ID;
    const int precedence;
};

class Multiplication : public Operator {
public:
    Multiplication() {
        ID = '*';
        precedence = 2;
    }
    virtual int evaluate(int left, int right) {
        return left * right;
    }
};

class Addition : public Operator {
public:
    Addition() {
        ID = '+';
        precedence = 1;
    }
    virtual int evaluate(int left, int right) {
        return left + right;
    }
};

// etc.

另外,我有点担心如何初始化常量,但这不是我的主要问题。

这听起来是使用std::function的一个很好的选择:

class Operator{
    public: //just for demonstration
    const char ID;
    const int precedence;
    std::function<int(int,int)> func;
}

//in main:
Operator Multiplication{
    '*',
    2,
    [](int a, int b){return a*b;}
};
类运算符{
公众:只是为了示范
常量字符ID;
常数优先;
std::函数func;
}
//大体上:
运算符乘法{
'*',
2.
[](inta,intb){返回a*b;}
};
这里的想法是:


使
操作符
成为存储std::函数或函数指针的类。然后创建类的加法、乘法等实例,并将每个实例传递给它自己的std::函数(这里我使用了lambda,但也可以使用普通函数)。当然,这只有在所有函数的签名都相同的情况下才有效,但从您的示例来看,它们似乎是相同的。

这听起来是使用std::function的一个不错的选择:

class Operator{
    public: //just for demonstration
    const char ID;
    const int precedence;
    std::function<int(int,int)> func;
}

//in main:
Operator Multiplication{
    '*',
    2,
    [](int a, int b){return a*b;}
};
类运算符{
公众:只是为了示范
常量字符ID;
常数优先;
std::函数func;
}
//大体上:
运算符乘法{
'*',
2.
[](inta,intb){返回a*b;}
};
这里的想法是:

使
操作符
成为存储std::函数或函数指针的类。然后创建类的加法、乘法等实例,并将每个实例传递给它自己的std::函数(这里我使用了lambda,但也可以使用普通函数)。当然,这只适用于所有函数的签名都相同的情况,但从您的示例来看,它们似乎是相同的。

您在评论中说:

我很担心,因为如果我定义了一个对象,它应该是一个包含与每个实例相关联的数据的对象。在这里,每个实例都是相同的,这让我很担心,但我看不到任何其他方法,因为我需要更改
evaluate
的实现

是的,每个对象的数据都是相同的。这是一个很好的观察。当每个对象的数据相同时,最好将其转换为
静态
成员数据和/或在适当时通过函数、虚拟函数提供对其的访问

这是您发布的代码的一个版本,它删除了成员数据,并提供了访问这些数据的
virtual
函数。这也消除了显式构造函数的需要

class Operator {
   public:
      virtual int evaluate(int left, int right) = 0;
      virtual char getID() const = 0;
      virtual int getPrecedence() const = 0;
};

class Multiplication : Operator {
   public:
      virtual char getID() const
      {
         return '*';
      }

      virtual int getPrecedence() const
      {
         return 2;
      }

      virtual int evaluate(int left, int right) {
         return left * right;
      }
};

class Addition : Operator {
   public:
      virtual char getID() const
      {
         return '+';
      }

      virtual int getPrecedence() const
      {
         return 1;
      }
      virtual int evaluate(int left, int right) {
         return left + right;
      }
};
你在评论中说:

我很担心,因为如果我定义了一个对象,它应该是一个包含与每个实例相关联的数据的对象。在这里,每个实例都是相同的,这让我很担心,但我看不到任何其他方法,因为我需要更改
evaluate
的实现

是的,每个对象的数据都是相同的。这是一个很好的观察。当每个对象的数据相同时,最好将其转换为
静态
成员数据和/或在适当时通过函数、虚拟函数提供对其的访问

这是您发布的代码的一个版本,它删除了成员数据,并提供了访问这些数据的
virtual
函数。这也消除了显式构造函数的需要

class Operator {
   public:
      virtual int evaluate(int left, int right) = 0;
      virtual char getID() const = 0;
      virtual int getPrecedence() const = 0;
};

class Multiplication : Operator {
   public:
      virtual char getID() const
      {
         return '*';
      }

      virtual int getPrecedence() const
      {
         return 2;
      }

      virtual int evaluate(int left, int right) {
         return left * right;
      }
};

class Addition : Operator {
   public:
      virtual char getID() const
      {
         return '+';
      }

      virtual int getPrecedence() const
      {
         return 1;
      }
      virtual int evaluate(int left, int right) {
         return left + right;
      }
};

允许多次实例化它吗?尽管如果类只是程序的核心功能,您也可以将其设置为
main
逻辑。过度工程毫无意义。这看起来像是可怕的结构和糟糕的OOP,那么我该如何用什么来取代它呢?您是否对发布的代码有不良体验?如果不是,是什么让你这么想的?@RSahu我很担心,因为如果我定义一个对象,它应该是一个包含与每个实例相关联的数据的对象。在这里,每个实例都是相同的,这让我很担心,但我看不到任何其他方法,因为我需要更改
evaluate
@Aposhian的实现。您不必创建很多实例,那么为什么要担心呢?另一方面,这些操作真的需要类型吗?我将实现一个二进制运算符类型,并为不同的算术运算提供不同的实例。允许它被实例化多次吗?尽管如果类只是程序的核心功能,您也可以将其设置为
main
逻辑。过度工程毫无意义。这看起来像是可怕的结构和糟糕的OOP,那么我该如何用什么来取代它呢?您是否对发布的代码有不良体验?如果不是,是什么让你这么想的?@RSahu我很担心,因为如果我定义一个对象,它应该是一个包含与每个实例相关联的数据的对象。在这里,每个实例都是相同的,这让我很担心,但我看不到任何其他方法,因为我需要更改
evaluate
@Aposhian的实现。您不必创建很多实例,那么为什么要担心呢?另一方面,这些操作真的需要类型吗?我将实现一个二进制运算符类型,并为不同的算术运算提供不同的实例。