问题描述
我的目标是在派生类上实现一个运算符,以便返回类型应该是派生类的。
我能够使用以下代码实现它:
#include <iostream>
class Base{
public:
virtual Base&& operator+ (const Base &b) = 0;
virtual void Val() = 0;
};
class Derived : public Base{
public:
Derived&& operator+ (const Base &b) override
{
Derived *res = new Derived;
auto tmp = dynamic_cast<const Derived*>(&b);
if(tmp) res->fVal = this->fVal+tmp->fVal;
return std::move(*res);
}
void SetVal(double val){fVal = val;}
void Val() override{std::cout<<"derived:"<<fVal<<std::endl;}
private:
double fVal{0};
};
int main(){
Derived a;
a.SetVal(2);
Derived b;
b.SetVal(3);
Base *baseptr = new Derived(a+b);
baseptr->Val();
Base &&d = a+b;
d.Val();
Derived e = dynamic_cast<Derived&>(d);
e.Val();
return 0;
}
我对返回类型使用右值引用不太满意,所以我想知道是否有我看不到的更简单的解决方案。返回派生类型的副本不起作用,因为 gcc 声明返回类型不是协变的。
编辑:正如@ofo 所提到的,我可以实现非常相似的返回左值引用的东西。目前它是最适合我的选项。但是,仍然不希望(至少可以说)有等待发生的内存泄漏,我只需要对 a+b;
解决方法
正如@Eljay 所建议的那样,我没有看到一种在不返回指针的情况下实现这一目标的方法。返回引用是可行的,但我认为无法确保调用者删除任何需要删除的内容。
我想到了这个(其中 func
代表我将使用运算符的场景):
#include <iostream>
#include <memory>
class Base{
public:
virtual std::unique_ptr<Base> operator+(const Base &) = 0;
virtual void SetVal(double) = 0;
virtual void Val() = 0;
};
class Derived : public Base{
public:
std::unique_ptr<Base> operator+(const Base &b) override
{
std::unique_ptr<Base> res = std::make_unique<Derived>();
auto tmp = dynamic_cast<const Derived*>(&b);
if(tmp) res->SetVal(this->fVal+tmp->fVal);
else std::cout<<"now i deal with invalid type case"<<std::endl;
return res;
}
void SetVal(double val) override{fVal = val;}
void Val(){std::cout<<fVal<<std::endl;}
private:
double fVal{0};
};
void func(Base &a,Base &b)
{
auto res = a+b;
res->Val();
}
int main(){
Derived a;
a.SetVal(2);
Derived b;
b.SetVal(3);
auto d = a+b;
d->Val();
func(a,b);
return 0;
}
如果有人找到更好的解决方案,我会暂时搁置。否则我会将其标记为答案。