【发布时间】:2020-03-27 11:35:26
【问题描述】:
我有以下 C++ 代码,它演示了我的问题。 我的目标是覆盖继承类中的流运算符,以便允许我根据对象类型打印特定的流:
#include <iostream>
#include <unordered_set>
using namespace std;
template <typename T>
class Base {
public:
Base(){}
Base(T n): value_(n){}
friend inline ostream &operator<<(ostream &os, const Base &b) {
b.to_str(os);
return os;
}
protected:
T value_;
// All object should implement this function
virtual void to_str(ostream& os) const {
os << value_;
}
};
template <typename T>
class Child: public Base<T> {
public:
Child(T n): Base<T>(n){}
protected:
void to_str(ostream& os) const override {
os << "{";
for (auto v = this->value_.begin(); v != this->value_.end(); v++) {
if(v != this->value_.begin())
os << ",";
os << (*v);
}
os << "}";
}
};
int main()
{
Base<string> b("base");
Child<unordered_set<string>> c({"child"});
cout << "b: " << b << endl;
cout << "c: " << c << endl;
return 0;
}
目前代码未编译:
main.cpp:31:16: error: no match for ‘operator<<’ (operand types are ‘std::ostream {aka std::basic_ostream}’ and ‘const std::unordered_set >’)
似乎编译器使用了来自 base 的虚方法 to_str(),而不是 Child 类的覆盖方法。 如果我注释了基础 to_str() 函数的主体,那么它会编译并打印 unordered_set Child 类的正确结果,但是它不会在基础实现中打印任何内容。 所以覆盖是有效的,但是为什么当 base to_str() 有一个主体时它不编译?
如何强制编译器使用派生的一个(子级)?
问候
【问题讨论】:
-
您没有正确复制错误消息。缺少一些碎片。
-
它将始终使用
to_str()的Child版本。但是编译器仍然希望为std::unordered_set生成函数Base::to_string(),这是合理的,因为它仍然可以被调用(并且在构建Base 期间需要该地址才能正确构建V-Table(假设实现使用V -Tables)。一个解决方案是在 Base 中将to_str()设为纯虚拟。然后必须为 Child 派生实现和一个新类 StandardStremable。 -
@MartinYork 感谢您的提示,正在考虑您提出的解决方案。我将发布修改后的代码。
标签: c++ inheritance operator-overloading operator-keyword