为什么我不能在派生类运算符>>中调用基类运算符>>?



假设我们有两个类:

class base{
protected:
char first_name;
public: 
/// constructors , destructor, operator= overloading ...

friend istream& operator >> (istream& in, base &client1) 
{
char f_name[1001];
cout << "First Name: ";
in >> f_name;
client1=base(f_name); /// class parameterised constructor;

return in;
}
};
class derived: public base{
protected:
char last_name[1001];
public: 
/// constructors , destructor, operator= overloading ...

friend istream& operator >> (istream& in, derived &client2) 
{
char l_name[1001], f_name[1001];

in >> (base) client2; /// it's not working like it dose in operator<<..
cout << "Last Name: ";
is >> l_name;
client2=derived(f_name, l_name); /// class parameterized constructor, 2 parameters because it use base constructor as well;

return in;
}
};

我重载了一些输出运算符(<<(,每次调用运算符<lt;从派生运算符<lt;。

我不知道这对运算符<lt;,我试了一下,但出了差错。当我调用基类运算符>gt;内部派生类运算符>gt;它给了我错误:

"对"operator>"的调用没有匹配函数>(std::istream&,abonament('|quot;

同样,如果我在运算符<lt,它运行良好:

friend ostream& operator << (ostream& out, derived &client) 
{

out << (base) client; /// it's working;

out << client.last_name;

return in;
}

是否可以调用基类运算符>gt;内部派生类运算符>gt>为什么会发生这种情况以及如何解决?(我希望我不必在派生类运算符中再次重写基类运算符中的相同行(

您已经成为对象切片的牺牲品。您可以通过强制转换到引用来解决眼前的问题。

在中

in >> (base) client2;

真正发生的是从client2生成一个新的临时Base,丢弃derived添加的所有成员。这是合法的。由于临时Base不能用作base &client1参数的参数,编译器会感到不安。临时变量就像它们听起来一样。它们存在的时间不长,所以引用一个是编译器阻止你犯的错误。如果它是合法的,临时变量将被Base>>运算符修改,然后在您可以使用读取到它的内容之前立即超出范围

in >> (base&) client2;

不进行切片,也不生成临时变量。client2更新成功。不幸的是,当

client2=derived(f_name, l_name);

用未初始化的变量CCD_ 9重写它。

因此,还需要更多的改变。

不要使用构造函数来完全重新创建和重新分配正在读入的对象。而是直接读取对象的成员变量。

示例:

class base{
protected:
char first_name[1001]; // need more than one character
public: 
/// constructors , destructor, operator= overloading ...

friend istream& operator >> (istream& in, base &client1) 
{
// char f_name[1001]; don't need. Read into member
cout << "First Name: ";
in >> client1.first_name; // read directly into member
// client1=base(f_name); don't need. Work done above

return in;
}
};
class derived: public base{
protected:
char last_name[1001];
public: 
/// constructors , destructor, operator= overloading ...

friend istream& operator >> (istream& in, derived &client2) 
{
//char l_name[1001], f_name[1001]; don't need. Use member variables

in >> (base&) client2; // client was being sliced. explanatory link above
//         ^ fixed with reference to allow polymorphism                             
cout << "Last Name: ";
in >> client2.last_name; // fixed typo. reading directly into member
// client2=derived(f_name, l_name); don't need. Work done above

return in;
}
};

旁注:这是对继承的滥用。实际上,这是在说姓氏就是名字。事实并非如此。阅读利斯科夫替代原则,找到一个好的规则,帮助确定继承何时有意义。以下是一些入门读物:利斯科夫替代原则的一个例子是什么?

旁注:>>向给定的char数组中读取一个以空格分隔的标记,即一个单词。这里有两个问题。最重要的是它不知道什么时候该停下来。1001个字符的数组只能部分缓解这种情况。用户需要长时间键入以溢出缓冲区,但不要怀疑人们这样做是为了好玩或盈利。使用std::string,问题就会消失。第二个问题是一个词的问题。这个解析器不能处理类似于"的名称;Billy Bob"或";von Doom";,幸运的是,这个姓氏的主人是虚构的,因为众所周知他是不可原谅的。

最新更新