如何创建使用重写函数的非成员函数?

How can I make a non-member function which uses an overridden function?

本文关键字:函数 重写 成员 何创建 创建      更新时间:2023-10-16

在此代码中,我尝试重载 += 操作。在非成员部分中一切看起来都很好,但是当我编写一个非成员函数时,(这部分的+操作)它给出了无效的抽象返回类型错误,并说+=操作在vector1d中是纯的。如何解决这个问题?

class AbstractBase{
public:
virtual AbstractBase &operator+=(const AbstractBase &other)=0;
private:
}
////   
class Vector1d:public AbstractBase{
public:
Vector1d &operator+=(const Vector1d &other);
private:
int size_;
vector<double> data_;
}
//non member func
Vector1d operator+(const Vector1d& vec1, const Vector1d& vec2);

///

Vector1d &Vector1d::operator+=(const Vector1d &other){
cout<<"sum operator is called"<<endl;
for(int i = 0; i < other.size_ ; i++)
data_.at(i) += other.data_.at(i);
return *this;
}
Vector1d operator+(const Vector1d& vec1, const Vector1d& vec2){
return  (Vector1d) vec1 += vec2;
};

重写时使用 C++11override上下文关键字。 这将使您的错误更接近您犯错误的地方。 也就是说,您没有覆盖。

你在别处被告知这一点,但这令人困惑。

这:

virtual AbstractBase &operator+=(const AbstractBase &other)=0;

具有与此不同的签名:

Vector1d &operator+=(const Vector1d &other);

第二个不会覆盖第一个。 它只是过载。 (他们是不同的!

此外,您还违反了LSP(见此处),这基本上表明您的设计存在根本错误。 我缺乏有关如何解决此问题的信息。 LSP 冲突不会导致生成中断。

要修复构建中断,只需执行以下操作:

Vector1d &operator+=(const AbstractBase &other) override; // and maybe final

(返回类型不完全匹配;这没关系,override关键字会检查它,因为 C++ 中的协变返回类型规则。 协方差不适用于任何合理语言中的const&参数(又名in)(逆变可能是明智的,但C++不是免费提供的,而且您无论如何都不会尝试这样做)。

而对于身体:

Vector1d &Vector1d::operator+=(const AbstractBase &other_abstract){
auto& other = dynamic_cast<Vector1d const&>(other_abstract); // can throw
std::cout<<"sum operator is called"<<std::endl;
for(int i = 0; i < other.size_ ; i++)
data_.at(i) += other.data_.at(i);
return *this;
}

现在,如果抽象类型与预期的类型不匹配,则会引发错误的强制转换。 这很可怕,但它会建立起来。

LSP 错误在于您的抽象基+=意味着任何具有相同抽象基底的任何两个对象都可以+='d。 您的实现不同意,非常明智。 这意味着你的阶级等级制度是垃圾,应该被抛弃,可能不会被取代。 但这是一个更广泛的问题,比我在关于您的技术构建中断的 SO 答案中涵盖的问题要广泛。

从根本上说,您永远不会覆盖operator+=(const AbstractBase &other)

您提供了一个采用const Vector1d&的新operator+=,但这只允许将+=与派生类型一起使用。

基类运算符+=可以与任何AbstractBase一起使用,因此当您重写它时,您需要保留签名,以便派生实现也适用于任何AbstractBase

这对于您的类层次结构可能没有意义,因此请仔细考虑抽象基类operator+=的效用。

即使Vector1d继承自AbstractBase

Vector1d &operator+=(const Vector1d &other);

没有与 相同的签名

AbstractBase &operator+=(const AbstractBase &other)=0

因此,它不能成为覆盖的候选项。