我一直试图找到答案,但似乎没有人和我有完全相同的问题。
我正在使用几个派生类。 ostream运算符<<对于每一个应该打印出一些共同的东西,以及每个特定的东西。稍后,我想进一步从这些派生类派生,并且新派生类需要打印出一些在它们上面的“代”中的东西。
例如:
基类.h文件
class Base
{
int FirstClassNumber;
//The declaration I'm currently working with, that a friend gave me
//I'm pretty sure my problem lies here.
public:
friend ostream& operator << (ostream& os, const Base &base)
{
base << os ;
return os;
}
virtual void operator << (ostream& os) const = 0;
};
Base.cpp文件包含以下行:
void Base::operator << (ostream& os)
{
os << FirstClassNumber;
}
然后我推导出:( FirstDerived.h)
class FirstDerived : Public Base
{
int SecondClassNumber;
};
FirstDerived.cpp:
FirstDerived::operator << (ostream& os)
{
os <<
"The first Number is:
//This is the line that isn't working - someone else gave me this syntax
<< Base::operator<<
<< "The second number is"
<< SecondClassNumber;
}
然后我想得出:
class SecondDerived: Public FirstDerived
{
int ThirdClassNumber;
};
Second.cpp:
FirstDerived::operator << (ostream& os)
{
os <<
FirstDerived::operator<<
<< "The third number is "
<< ThirdClassNumber;
}
我认为问题很可能是在程序开始时的声明,或者像Base::operator<<
这样的行。
另一种可能性是我没有在每个继承类的.h文件中重新声明它。我应该是,如果是,我应该使用什么语法?
有人建议我使用static_cast
方法,但我的教授(编写任务的人,因此不会给我们太多的帮助)说有更好的方法它。有什么建议吗?
答案 0 :(得分:13)
一个简单的技巧是:
class Base
{
int FirstClassNumber;
public:
virtual void serialize(ostream& os) const
{
os << FirstClassNumber;
}
};
// Implement the stream operator for the base class.
// All it does is call erialize which is a virtual method that
// will call the most derived version.
ostream& operator << (ostream& os, const Base &base)
{
base.serialize(os);
return os;
}
class FirstDerived:public Base
{
int SecondClassNumber;
public:
// Override serialize to make it call the base version.
// Then output any local data.
virtual void serialize(ostream& os) const
{
Base::serialize(os);
os << SecondClassNumber;
}
};
答案 1 :(得分:6)
您无法实现运算符&lt;&lt;对于ostreams作为类成员 - 它必须是一个免费(可能是朋友)的功能。这是因为在表达式中:
os << x;
&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;将不是您的类的实例,如果它是成员函数则必须是它。
要从孩子那里呼叫父母 - 做一个static_cast:
ostream & operator << ( ostream & os, const Child & c ) {
os << static_cast <const Parent &>( c );
// child stuff here
}
我认为这是“最佳”解决方案。或者,为您的类提供一个命名函数调用Print(),它将ostream作为参数并使用它来实现您的运算符&lt;&lt;。这将导致更多的清理程序代码。
答案 2 :(得分:2)
除了@Neil所说的,实现虚拟DoStream
方法可能更好,因此您不需要上传:
class Base{
private:
virtual void DoStream(ostream& os){
// general stuff
}
public:
friend ostream& operator<<(ostream& os, Base& b){
b.DoStream(os);
return os;
}
};
class Derived : public Base{
private:
void DoStream(ostream& os){
Base::DoStream(os);
// derived specific stuff
}
};
所以你只需要实现一次运算符。您也可以将operator<<
非朋友和DoStream
公开,但这可能是个人偏好。
答案 3 :(得分:1)
FirstDerived.cpp:
FirstDerived::operator << (ostream& os)
{
os << "The first Number is:"
//This is the line that isn't working - someone else gave me this syntax
<< Base::operator<<
<< "The second number is"
<< SecondClassNumber;
}
您需要通过在其后面添加括号来调用该函数,并提供它所期望的参数。它没有返回值,因此不应该在流式传输的集合中。概括地:
os << "The first number is: "; // finish streaming statement with ";"
Base::operator<<(os); // separate statement to call this function...
os << "The second number is " << SecondClassNumber; // start streaming again
答案 4 :(得分:0)
要从基类调用方法,您可以使用:
Base::method(/*parameters*/)
但是operator<<
是一个自由函数。我可以看到没有static_cast的唯一可能性是将运算符定义为模板,然后显式调用这样的特化:
template<typename T>
void function(T const &t);
template<>
void function<Base>(Base const &t) {
// own implementation ...
}
template<>
void function<Derived>(Derived const &t) {
function<Base>(t);
// own implementation ...
}
对于运营商&lt;&lt;,可以采用相同的方式完成此操作,只需更改function
的名称operator<<
并添加所需的参数。
另一种可能性是制作虚拟成员函数:
class Base {
virtual void print(ostream &os) const {
// print self
}
};
在Derived类中,这可以调用Base打印功能:
class Derived {
virtual void print(ostream &os) const {
Base::print(os);
// print self
}
};
然后只有operator<<
类的Base
就足够了,它会调用适当的print方法多态。请注意,operator<<
是一个免费功能。
ostream &operator<< (ostream &os, Base const &b) {
b.print(os);
return os;
}
答案 5 :(得分:0)
这里对Loki的答案略有修改。我没有使用虚拟序列化方法,而是使用虚拟的to_string方法。我认为这可以在输出到ostream的更多上下文中重用,这可能是有用的。
#include <iostream>
#include <string>
class Base
{
public:
Base();
virtual std::string to_string() const;
protected:
int first_class_number;
friend std::ostream& operator<<(std::ostream& os, const Base &base);
};
Base::Base()
: first_class_number(1)
{
}
std::string Base::to_string() const
{
return "Base: "+std::to_string(first_class_number);
}
class FirstDerived : public Base
{
public:
FirstDerived();
std::string to_string() const;
protected:
int second_class_number;
};
FirstDerived::FirstDerived()
: second_class_number(2)
{
}
std::string FirstDerived::to_string() const
{
return "FirstDerived: "+std::to_string(first_class_number)+" "+ std::to_string(second_class_number);
}
std::ostream& operator << (std::ostream& os, const Base &base)
{
os << base.to_string();
return os;
}
int main(int argc, const char *argv[])
{
std::cout << Base() << std::endl;
std::cout << FirstDerived() << std::endl;
return 0;
}
可生产
Base: 1
FirstDerived: 1 2