我正试图在c++类中编写命题逻辑公式。公式可以是:
一个变量- 公式的否定
- 两个由连接符 连接的公式
我无法定义一种方法将这三种不同的结构定义到一个类中,所以我决定将它们声明为不同的子类。我遇到的问题是,当声明操作符时,它们似乎没有正确地覆盖标准操作符。,,返回bool值而不是shared_ptr
解决:只是在基类中使用shared_ptr来避免任何切片。
#include <iostream>
#include <memory>
using namespace std;
// {0, 1, 2}
// {and, or, implies}
class formula
{
shared_ptr <formula> F;
public:
formula ()
{}
formula (shared_ptr <formula> f)
{
F = f;
}
formula (formula* f)
{
F = shared_ptr <formula> (f);
}
virtual bool evaluate ()
{
return F -> evaluate ();
}
virtual string type ()
{
return F -> type ();
}
shared_ptr <formula> address ()
{
return F;
}
virtual void assign (bool b)
{
F -> assign (b);
}
formula operator&& (formula f);
formula operator|| (formula f);
formula operator>> (formula f);
formula operator! ();
};
class variable : public formula
{
bool value;
public:
void assign (bool b)
{
value = b;
}
bool evaluate ()
{
return value;
}
string type ()
{
return "variable";
}
};
class negation : public formula
{
shared_ptr <formula> arg;
public:
negation (formula f)
{
arg = f.address ();
}
bool evaluate ()
{
return !(arg -> evaluate ());
}
string type ()
{
return "negation";
}
};
class connected : public formula
{
shared_ptr <formula> lhs, rhs;
int C;
public:
connected (formula f, formula g, int c)
{
lhs = f.address ();
rhs = g.address ();
C = c;
}
bool evaluate ()
{
if (C == 0)
return lhs -> evaluate () && rhs -> evaluate ();
else if (C == 1)
return lhs -> evaluate () || rhs -> evaluate ();
else
return !(lhs -> evaluate ()) || rhs -> evaluate ();
}
string type ()
{
return "connected";
}
};
formula formula::operator&& (formula g)
{
shared_ptr <formula> temp (new connected (*this, g, 0));
formula f (temp);
return f;
}
formula formula::operator|| (formula g)
{
shared_ptr <formula> temp (new connected (*this, g, 1));
formula f (temp);
return f;
}
formula formula::operator>> (formula g)
{
shared_ptr <formula> temp (new connected (*this, g, 2));
formula f (temp);
return f;
}
formula formula::operator! ()
{
shared_ptr <formula> temp (new negation (*this));
formula f (temp);
return f;
}
int main ()
{
formula A (new variable), B (new variable);
A.assign(true);
B.assign(false);
formula x = A&&B, y = A||B, z = A>>B, w = !B;
cout << boolalpha;
cout << x.evaluate () << endl;
cout << y.evaluate () << endl;
cout << z.evaluate () << endl;
cout << w.evaluate () << endl << endl;
B.assign(true);
cout << boolalpha;
cout << x.evaluate () << endl;
cout << y.evaluate () << endl;
cout << z.evaluate () << endl;
cout << w.evaluate () << endl;
}
定义&&
接受formula
和shared_ptr<formula>
类型的参数。这是一种奇怪的不对称,会让你困惑不已。然后你试着把它应用到两个shared_ptr<formula>
上。这是行不通的。
作为权宜之计,更改
cerr << (A&&B) -> type () << endl;
cerr << (*A && B) -> type () << endl;
然而从长远来看,这是不可持续的。
我建议将formula
拆分为两个类,formula
和formula_impl
,其中formula_impl
包含前formula
的所有虚函数,formula
包含shared_ptr<formula_impl>
。formula
实现了它所能实现的(operator&&
以及将来可能会实现的其他东西,如operator!
和operator||
等等),并将evaluate
等委托给共享指针指向的formula_impl
。最终用户只能看到formula
,看不到formula_impl
。
formula
还应该定义静态函数,返回一个变量、一个否定和一个连接。
附加说明
对于虚函数来说,assign
不是一个很好的选择。你只能赋值一个变量。这对其他类型的公式没有意义。我将完全去掉这个函数,并将值传递给variable
的构造函数。
基类实现不应该打印"错误"或做任何其他事情。它们应该是纯虚函数。
幻数(0是合取,1是析取)不是一个好主意。定义一个enum
。将default
的情况视为错误。