我来自python世界,其中__str__
和__repr__
对我的开发和执行工作流输出非常有用。
我想用C ++实现这些东西。
This post一直很有用,但我希望字符串输出包含类名,并且子类可以轻松地重载。
这是一个代码示例:
#include<iostream>
#include<string>
class Parent
{
static constexpr const char* clsName = "Parent";
std::string _label;
public:
Parent(std::string& label) : _label(label) {}
friend std::ostream &operator<<(std::ostream &os,
Parent const &ref)
{
os << clsName << "(";
ref.print(os);
os << ")";
return os;
}
void print(std::ostream &os) const
{ os << _label; }
};
class Child : public Parent
{
static constexpr const char* clsName = "Child";
public:
Child(std::string& label) : Parent(label) {}
};
我的意图是Child::operator<<
使用它自己的clsName
静态私有数据,而不必为每个子类重载整个运算符。
不幸的是,这种策略不起作用:
int main()
{
std::string l("some label");
Child x(l);
std::cout << x << std::endl;
}
将输出
Parent(some label)
(我希望看到Child(some label)
)。
答案 0 :(得分:1)
我会添加一个virtual
成员函数来获取类名。
我还会使print
成为virtual
成员函数,以允许派生类增强在基类中完成的操作。
我建议进行更多改进:
const&
。operator<<
功能不一定是friend
。这是您课程的更新版本。
class Parent
{
private:
static constexpr const char* clsName = "Parent";
std::string _label;
public:
Parent(std::string const& label) : _label(label) {}
virtual std::string getClassName() const
{
return clsName;
}
virtual void print(std::ostream &os) const
{
os << _label;
}
};
std::ostream &operator<<(std::ostream &os, Parent const &ref)
{
os << ref.getClassName() << "(";
ref.print(os);
os << ")";
return os;
}
class Child : public Parent
{
private:
static constexpr const char* clsName = "Child";
public:
virtual std::string getClassName() const
{
return clsName;
}
virtual void print(std::ostream &os) const
{
// Nothing to do for this class in particual.
// Just use the Parent implementation.
Parent::print(os);
}
Child(std::string const& label) : Parent(label) {}
};
答案 1 :(得分:0)
您需要使clsName
成为虚拟功能。目前Child::clsName
仅隐藏Parent::clsName
,您仍可以Parent::clsName
内访问Child
。
您还应该声明Parent
的析构函数是虚拟的,这意味着还应该声明其他特殊成员。所有五个都可以实现为= default
。
#include<iostream>
#include<string>
class Parent
{
virtual std::string clsName() const { return "Parent" };
std::string _label;
public:
Parent(const std::string& label) : _label(label) {}
virtual ~Parent() = default;
Parent(const Parent &) = default;
Parent(Parent &&) = default;
Parent& operator=(const Parent &) = default;
Parent& operator=(Parent &&) = default;
friend std::ostream &operator<<(std::ostream &os, Parent const &ref)
{
return os << ref.clsName() << "(" << ref._label << ")";
}
};
class Child : public Parent
{
std::string clsName() const override { return "Child" };
public:
using Parent::Parent;
};