全局class与继承的比较
Global class comparison with inheritance
我正在用 operator==
为大型框架编写全局 class 比较函数,其中 classes 倾向于继承多个 classes 或具有深度继承(class A
继承自 B
,B
继承自 C
,等等)。为了使事情易于管理,我想我会为基础 classes 设置一个比较函数,然后从基础继承的 classes 除了检查自己的成员
之外还会使用该函数]
谷歌搜索,我找到了比较 classes 的示例代码,但没有涉及继承的示例。下面我为 base class Foo
编写了一个简单的示例,其中 Bar
继承自:
#include <iostream>
class Foo
{
public:
int m_a;
Foo(int i) : m_a(i) {}
};
inline static bool operator==(const Foo& l, const Foo& r)
{
return l.m_a == r.m_a;
}
static void coutResult(const Foo& l, const Foo&r)
{
std::cout << "l.m_a == " << l.m_a << ", "
<< "r.m_a == " << r.m_a << ", "
<< (l == r ? "true" : "false") << std::endl;
}
class Bar :
public Foo
{
public:
int m_b;
Bar(int i, int j) : Foo(i), m_b(j) {}
};
inline static bool operator==(const Bar& l, const Bar& r)
{
return ((Foo)l) == ((Foo)r) &&
l.m_b == r.m_b;
}
static void coutResult(const Bar& l, const Bar& r)
{
std::cout << "l.m_a == " << l.m_a << ", "
<< "l.m_b == " << l.m_b << ", "
<< "r.m_a == " << r.m_a << ", "
<< "r.m_b == " << r.m_b << ", "
<< (l == r ? "true" : "false") << std::endl;
}
int main(int argc, char** argv) {
Foo a(1);
Foo b(1);
Foo c(2);
coutResult(a, b);
coutResult(a, c);
coutResult(a, c);
Bar d(1, 2);
Bar e(1, 2);
Bar f(1, 3);
Bar g(2, 2);
coutResult(d, e);
coutResult(d, f);
coutResult(d, g);
coutResult(e, f);
coutResult(f, g);
coutResult(f, g);
return 0;
}
它似乎工作得很好,但我想知道是否有 "standard" 方法来解决这个问题或更好的解决方案。这个解决方案有两个问题:
每次开发人员向某些 class 添加成员时,他们都必须知道更新相应的比较函数,但我看不出如何避免这种情况
没有成员可以设为私有,考虑到框架很大,这是一个问题。我知道的唯一解决方案是为每个私有成员
制作一个getter
您的设计有可能产生意想不到的结果。
如果您的 main
是:
int main(int argc, char** argv)
{
Foo a(1);
Bar d(1, 2);
coutResult(a, d);
return 0;
}
您最终会将 Foo
对象与 Bar
对象进行比较,输出将是:
l.m_a == 1, r.m_a == 1, true
如果您对这个结果感到满意,您可以坚持目前的设计。但是,我认为这是一个不合适的结果。
我的建议:
- 将
Foo
设为纯虚拟 class 以避免出现类似情况。
- 使
operator=()
成为Foo
的纯虚成员函数。在 Foo
中提供一个实现,派生的 class 实现可以利用。
- 实现派生的 classes 函数。使用
dynamic_cast
确保您将 Bar
与另一个 Bar
进行比较,而不是将 Bar
与 Foo
. 的另一个子类型进行比较
这是一个演示这些想法的程序。
#include <iostream>
class Foo
{
public:
int m_a;
Foo(int i) : m_a(i) {}
virtual bool operator==(const Foo& r) const = 0;
};
bool Foo::operator==(const Foo& r) const
{
return (this->m_a == r.m_a);
}
static void coutResult(const Foo& l, const Foo&r)
{
std::cout << std::boolalpha << (l == r) << std::endl;
}
class Bar : public Foo
{
public:
int m_b;
Bar(int i, int j) : Foo(i), m_b(j) {}
virtual bool operator==(const Foo& r) const
{
Bar const* barPtr = dynamic_cast<Bar const*>(&r);
if ( barPtr == nullptr )
{
return false;
}
if ( !Foo::operator==(r) )
{
return false;
}
return (this->m_b == barPtr->m_b);
}
};
class Baz : public Foo
{
public:
double m_c;
Baz(int i, double c) : Foo(i), m_c(c) {}
virtual bool operator==(const Foo& r) const
{
Baz const* bazPtr = dynamic_cast<Baz const*>(&r);
if ( bazPtr == nullptr )
{
return false;
}
if ( !Foo::operator==(r) )
{
return false;
}
return (this->m_c == bazPtr->m_c);
}
};
int main(int argc, char** argv)
{
Bar bar1(1, 2);
Bar bar2(1, 2);
Bar bar3(2, 2);
Baz baz1(1, 10.8);
Baz baz2(1, 10.8);
coutResult(bar1, bar2);
coutResult(bar1, bar3);
coutResult(bar1, baz1);
coutResult(baz1, baz2);
return 0;
}
输出:
true
false
false
true
我正在用 operator==
为大型框架编写全局 class 比较函数,其中 classes 倾向于继承多个 classes 或具有深度继承(class A
继承自 B
,B
继承自 C
,等等)。为了使事情易于管理,我想我会为基础 classes 设置一个比较函数,然后从基础继承的 classes 除了检查自己的成员
谷歌搜索,我找到了比较 classes 的示例代码,但没有涉及继承的示例。下面我为 base class Foo
编写了一个简单的示例,其中 Bar
继承自:
#include <iostream>
class Foo
{
public:
int m_a;
Foo(int i) : m_a(i) {}
};
inline static bool operator==(const Foo& l, const Foo& r)
{
return l.m_a == r.m_a;
}
static void coutResult(const Foo& l, const Foo&r)
{
std::cout << "l.m_a == " << l.m_a << ", "
<< "r.m_a == " << r.m_a << ", "
<< (l == r ? "true" : "false") << std::endl;
}
class Bar :
public Foo
{
public:
int m_b;
Bar(int i, int j) : Foo(i), m_b(j) {}
};
inline static bool operator==(const Bar& l, const Bar& r)
{
return ((Foo)l) == ((Foo)r) &&
l.m_b == r.m_b;
}
static void coutResult(const Bar& l, const Bar& r)
{
std::cout << "l.m_a == " << l.m_a << ", "
<< "l.m_b == " << l.m_b << ", "
<< "r.m_a == " << r.m_a << ", "
<< "r.m_b == " << r.m_b << ", "
<< (l == r ? "true" : "false") << std::endl;
}
int main(int argc, char** argv) {
Foo a(1);
Foo b(1);
Foo c(2);
coutResult(a, b);
coutResult(a, c);
coutResult(a, c);
Bar d(1, 2);
Bar e(1, 2);
Bar f(1, 3);
Bar g(2, 2);
coutResult(d, e);
coutResult(d, f);
coutResult(d, g);
coutResult(e, f);
coutResult(f, g);
coutResult(f, g);
return 0;
}
它似乎工作得很好,但我想知道是否有 "standard" 方法来解决这个问题或更好的解决方案。这个解决方案有两个问题:
每次开发人员向某些 class 添加成员时,他们都必须知道更新相应的比较函数,但我看不出如何避免这种情况
没有成员可以设为私有,考虑到框架很大,这是一个问题。我知道的唯一解决方案是为每个私有成员
制作一个getter
您的设计有可能产生意想不到的结果。
如果您的 main
是:
int main(int argc, char** argv)
{
Foo a(1);
Bar d(1, 2);
coutResult(a, d);
return 0;
}
您最终会将 Foo
对象与 Bar
对象进行比较,输出将是:
l.m_a == 1, r.m_a == 1, true
如果您对这个结果感到满意,您可以坚持目前的设计。但是,我认为这是一个不合适的结果。
我的建议:
- 将
Foo
设为纯虚拟 class 以避免出现类似情况。 - 使
operator=()
成为Foo
的纯虚成员函数。在Foo
中提供一个实现,派生的 class 实现可以利用。 - 实现派生的 classes 函数。使用
dynamic_cast
确保您将Bar
与另一个Bar
进行比较,而不是将Bar
与Foo
. 的另一个子类型进行比较
这是一个演示这些想法的程序。
#include <iostream>
class Foo
{
public:
int m_a;
Foo(int i) : m_a(i) {}
virtual bool operator==(const Foo& r) const = 0;
};
bool Foo::operator==(const Foo& r) const
{
return (this->m_a == r.m_a);
}
static void coutResult(const Foo& l, const Foo&r)
{
std::cout << std::boolalpha << (l == r) << std::endl;
}
class Bar : public Foo
{
public:
int m_b;
Bar(int i, int j) : Foo(i), m_b(j) {}
virtual bool operator==(const Foo& r) const
{
Bar const* barPtr = dynamic_cast<Bar const*>(&r);
if ( barPtr == nullptr )
{
return false;
}
if ( !Foo::operator==(r) )
{
return false;
}
return (this->m_b == barPtr->m_b);
}
};
class Baz : public Foo
{
public:
double m_c;
Baz(int i, double c) : Foo(i), m_c(c) {}
virtual bool operator==(const Foo& r) const
{
Baz const* bazPtr = dynamic_cast<Baz const*>(&r);
if ( bazPtr == nullptr )
{
return false;
}
if ( !Foo::operator==(r) )
{
return false;
}
return (this->m_c == bazPtr->m_c);
}
};
int main(int argc, char** argv)
{
Bar bar1(1, 2);
Bar bar2(1, 2);
Bar bar3(2, 2);
Baz baz1(1, 10.8);
Baz baz2(1, 10.8);
coutResult(bar1, bar2);
coutResult(bar1, bar3);
coutResult(bar1, baz1);
coutResult(baz1, baz2);
return 0;
}
输出:
true
false
false
true