gpt4 book ai didi

c++ - 类多态性和相等运算符

转载 作者:搜寻专家 更新时间:2023-10-31 01:01:18 25 4
gpt4 key购买 nike

我正在努力解决我已经想了很久的事情。假设我有一个类 Base

class Base
{
public:
virtual ~Base(){}
virtual bool operator== ( const Base & rhs ) const;
};

现在,另一个类继承自它。它有两个相等运算符:

class A : public Base
{
public:
bool operator== ( const A & rhs ) const;
bool operator== ( const Base & rhs ) const;
private:
int index__;
};

还有另一个类也继承自 Base,它也有两个相等运算符:

class B : public Base
{
public:
bool operator== ( const B & rhs ) const;
bool operator== ( const Base & rhs ) const;
private:
int index__;
};

这是我的理解(不一定正确)。我只能使用第一个运算符来检查同一类对象是否相等。然而,我可以使用第二个运算符来检查它们是否是同一类型的类,然后检查它们是否相等。现在,又存在另一个类,它包装了 Base 的指针,但是,它们是多态类型 A 或 B。

class Z
{
public:
bool operator== ( const Z & rhs ) const;
private:
std::shared_ptr<Base> ptr__;
};

首先,我发现我不能让两个 operator== 重载。我没有从编译器中得到任何错误,但是当我尝试运行它时,它只是挂起。我猜它与 rtti 有关,这超出了我的范围。

我一直在使用的是非常丑陋的尝试向下转换,如果可以的话,然后尝试比较类 Z 中的实例:

bool Z::operator== ( const Z & rhs ) const
{
if ( const auto a1 = std::dynamic_pointer_cast<A>( this->ptr__ ) )
if ( const auto a2 = std::dynamic_pointer_cast<A>( rhs.ptr__ ) )
return *a1 == *a2;
else if ( const auto b1 = std::dynamic_pointer_cast<B>( this->ptr__ ) )
if ( const auto b2 = std::dynamic_pointer_cast<B>( rhs.ptr__ ) )
return *b1 == *b2;
return false;
}

这很丑陋,它假定您的类 A 和 B 有一个相等运算符,该运算符将相同类型的类作为参数。

所以我试图想出一种方法,它会使用第二种类型的运算符,如果你愿意的话,它更不可知,更优雅。失败了。这将需要在 A 类和 B 类中都使用它,从而将它从 Z 类中移开。

bool A::operator== ( const Base & rhs ) const
{
return ( typeid( *this ) == typeid( rhs ) ) && ( *this == rhs );
}

对于 B 类也是如此。这似乎不起作用(应用挂起且没有任何错误)。此外,它使用某种默认运算符,还是使用基类运算符?理想情况下,它应该同时使用 Base::operator== 和比较类类型。

但是,如果我想要基于类 A 或 B 的成员(例如 index__)进行更详细的比较,那么我显然必须为每个类加好友,因为当我尝试这样做时,它不会编译(当然除非我添加一个 getter 或者让它以某种方式可见):

bool A::operator== ( const Base & rhs ) const
{
return ( typeid( *this ) == typeid( rhs ) )
&& (*this == *rhs )
&& (this->index__ == rhs.index__ );
}

是否有优雅、简单的解决方案?我是否仅限于沮丧和尝试,还是有其他方法可以实现我想要的?

最佳答案

我同意@vsoftco 关于仅在基类中实现operator== 并使用NVI 习惯用法的观点。但是,我会提供派生类需要实现的纯虚函数来执行相等性检查。通过这种方式,基类不知道也不关心任何派生类等价意味着什么。

代码

#include <iostream>
#include <string>
#include <typeinfo>

class Base
{
public:
virtual ~Base() {}

bool operator==(const Base& other) const
{
// If the derived types are the same then compare them
return typeid(*this) == typeid(other) && isEqual(other);
}

private:
// A pure virtual function derived classes must implement.
// Furthermore, this function has a precondition that it will only
// be called when the 'other' is the same type as the instance
// invoking the function.
virtual bool isEqual(const Base& other) const = 0;
};

class D1 : public Base
{
public:
explicit D1(double v = 0.0) : mValue(v) {}
virtual ~D1() override {}

private:
virtual bool isEqual(const Base& other) const
{
// The cast is safe because of the precondition documented in the
// base class
return mValue == static_cast<const D1&>(other).mValue;
}

private:
double mValue;
};

class D2 : public Base
{
public:
explicit D2(std::string v = "") : mValue(v) {}
virtual ~D2() override {}

private:
virtual bool isEqual(const Base& other) const
{
return mValue == static_cast<const D2&>(other).mValue;
}

private:
std::string mValue;
};

class D3 : public Base
{
public:
explicit D3(int v = 0) : mValue(v) {}
virtual ~D3() override {}

private:
virtual bool isEqual(const Base& other) const
{
return mValue == static_cast<const D3&>(other).mValue;
}

private:
int mValue;
};

int main()
{
D1 d1a(1.0);
D1 d1b(2.0);
D1 d1c(1.0);

D2 d2a("1");
D2 d2b("2");
D2 d2c("1");

D3 d3a(1);
D3 d3b(2);
D3 d3c(1);

std::cout << "Compare D1 types\n";
std::cout << std::boolalpha << (d1a == d1b) << "\n";
std::cout << std::boolalpha << (d1b == d1c) << "\n";
std::cout << std::boolalpha << (d1a == d1c) << "\n";

std::cout << "Compare D2 types\n";
std::cout << std::boolalpha << (d2a == d2b) << "\n";
std::cout << std::boolalpha << (d2b == d2c) << "\n";
std::cout << std::boolalpha << (d2a == d2c) << "\n";

std::cout << "Compare D3 types\n";
std::cout << std::boolalpha << (d3a == d3b) << "\n";
std::cout << std::boolalpha << (d3b == d3c) << "\n";
std::cout << std::boolalpha << (d3a == d3c) << "\n";

std::cout << "Compare mixed derived types\n";
std::cout << std::boolalpha << (d1a == d2a) << "\n";
std::cout << std::boolalpha << (d2a == d3a) << "\n";
std::cout << std::boolalpha << (d1a == d3a) << "\n";
std::cout << std::boolalpha << (d1b == d2b) << "\n";
std::cout << std::boolalpha << (d2b == d3b) << "\n";
std::cout << std::boolalpha << (d1b == d3b) << "\n";
std::cout << std::boolalpha << (d1c == d2c) << "\n";
std::cout << std::boolalpha << (d2c == d3c) << "\n";
std::cout << std::boolalpha << (d1c == d3c) << "\n";

return 0;
}

输出

Compare D1 types
false
false
true
Compare D2 types
false
false
true
Compare D3 types
false
false
true
Compare mixed derived types
false
false
false
false
false
false
false
false
false

关于c++ - 类多态性和相等运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29380047/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com