实例化派生的 class 只有一次糟糕的 OOP?
Is instantiating a derived class only once bad OOP?
我有一个 class 结构,它打算只让我派生的 classes 每个只实例化一次。在我看来,这就像糟糕的 OOP,因为多个实例将是相同的并且毫无用处,所以我应该替换它吗?
上下文:
我正在为计算器应用程序构建基础。我有一个 Operator
class Multiplication
、Addition
等继承自。我使用 Operator
作为抽象基础 class,然后 "Calculator" 包含一个 Operator*
的多态容器,支持一个操作实例,因此它可以调用 evaluate
只需匹配 ID 即可在 Operator 上使用。
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;}
};
这里的想法是这样的:
使 Operator
成为存储 std::function 或函数指针的 class。然后创建 class 的加法、乘法等实例,并将每个实例传递给自己的 std::function(这里我使用了 lambda,但您也可以使用普通函数)。当然这只有在所有函数的签名都相同的情况下才有效,但从你的例子看来它们是相同的。
您在评论中说:
Well I was concerned, because it seems like if I am defining an object, it should be a thing that has data associated with each instance. Here, every instance would be identical, which worries me, but I couldn't see any other way since I needed to change implementation of evaluate
.
是的,每个对象的数据都是相同的。这是一个很好的观察。当每个对象的数据相同时,最好将它们变成 static
成员数据 and/or 通过函数提供对它们的访问,virtual
在适当的时候使用函数。
这是您发布的代码的一个版本,它删除了成员数据并提供了 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;
}
};
我有一个 class 结构,它打算只让我派生的 classes 每个只实例化一次。在我看来,这就像糟糕的 OOP,因为多个实例将是相同的并且毫无用处,所以我应该替换它吗?
上下文:
我正在为计算器应用程序构建基础。我有一个 Operator
class Multiplication
、Addition
等继承自。我使用 Operator
作为抽象基础 class,然后 "Calculator" 包含一个 Operator*
的多态容器,支持一个操作实例,因此它可以调用 evaluate
只需匹配 ID 即可在 Operator 上使用。
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;}
};
这里的想法是这样的:
使 Operator
成为存储 std::function 或函数指针的 class。然后创建 class 的加法、乘法等实例,并将每个实例传递给自己的 std::function(这里我使用了 lambda,但您也可以使用普通函数)。当然这只有在所有函数的签名都相同的情况下才有效,但从你的例子看来它们是相同的。
您在评论中说:
Well I was concerned, because it seems like if I am defining an object, it should be a thing that has data associated with each instance. Here, every instance would be identical, which worries me, but I couldn't see any other way since I needed to change implementation of
evaluate
.
是的,每个对象的数据都是相同的。这是一个很好的观察。当每个对象的数据相同时,最好将它们变成 static
成员数据 and/or 通过函数提供对它们的访问,virtual
在适当的时候使用函数。
这是您发布的代码的一个版本,它删除了成员数据并提供了 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;
}
};