为什么我不能在派生 class 运算符>> 中调用基础 class 运算符>>?
Why i can't call base class operator>> in derived class operator>>?
假设我们有 2 classes :
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;
}
};
我重载了一些输出运算符 (<<),每次我从派生运算符 << 中的基调用运算符 << 时,它似乎都运行良好。
我不知道这对运算符<<是否同样有效,我尝试了一些但它给出了错误。
当我调用 base class operator>> 在 derived class operator>> 中时,它给我错误:
" no matching function for call to 'operator>>(std::istream&,
abonament)'| "
同样,如果我在 operator<< 中做同样的事情,它工作正常:
friend ostream& operator << (ostream& out, derived &client)
{
out << (base) client; /// it's working;
out << client.last_name;
return in;
}
是否可以在派生的 class 运算符中调用基 class 运算符>> >>>
为什么会发生这种情况以及如何解决?
(我希望我不必在派生 class 运算符>> 中再次重写基 class 运算符>> 中的相同行)
您已成为 object slicing 的牺牲品。您可以通过转换为参考来解决眼前的问题。
在
in >> (base) client2;
真正发生的是一个新的临时 Base
是由 client2
生成的,丢弃了 derived
的所有添加成员。这是合法的。编译器不高兴,因为临时 Base
不能用作 base &client1
参数的参数。临时变量就像它们听起来一样。它们的存在时间不长,因此引用一个是编译器阻止您犯的错误。如果它是合法的,临时变量将被 Base
的 >>
运算符修改,然后在您可以使用读入它的内容之前立即超出范围。
in >> (base&) client2;
不分片也不做临时变量。 client2
更新成功。不幸的是,这项工作在
时被丢弃了
client2=derived(f_name, l_name);
用未初始化的变量覆盖它 l_name
。
因此需要进行更多更改。
不要使用构造函数来完全重新创建和重新分配您正在读入的对象。而是直接读入对象的成员变量。
示例:
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;
}
};
旁注:这是对继承的滥用。这实际上是说姓氏 is-a first name. Which it isn't. Read up on the Liskov Substitution principle for a good rule to help determine when inheritance makes sense. Here's some starter reading: What is an example of the Liskov Substitution Principle?
旁注:>>
将一个空格分隔的标记(一个词)读入给定的 char
数组。这里有两个问题。最重要的是它不知道什么时候停止。 1001 字符数组只能部分缓解这种情况。用户需要长时间键入才能溢出缓冲区,但不要怀疑人们会为了乐趣或利益而这样做。使用 std::string
代替,问题就消失了。第二个问题是整个一个词的事情。此解析器无法处理诸如“Billy Bob”或“von Doom”之类的名称,幸运的是,该姓氏的所有者是虚构的,因为他是众所周知的不宽容。
假设我们有 2 classes :
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;
}
};
我重载了一些输出运算符 (<<),每次我从派生运算符 << 中的基调用运算符 << 时,它似乎都运行良好。
我不知道这对运算符<<是否同样有效,我尝试了一些但它给出了错误。 当我调用 base class operator>> 在 derived class operator>> 中时,它给我错误:
" no matching function for call to 'operator>>(std::istream&, abonament)'| "
同样,如果我在 operator<< 中做同样的事情,它工作正常:
friend ostream& operator << (ostream& out, derived &client)
{
out << (base) client; /// it's working;
out << client.last_name;
return in;
}
是否可以在派生的 class 运算符中调用基 class 运算符>> >>> 为什么会发生这种情况以及如何解决? (我希望我不必在派生 class 运算符>> 中再次重写基 class 运算符>> 中的相同行)
您已成为 object slicing 的牺牲品。您可以通过转换为参考来解决眼前的问题。
在
in >> (base) client2;
真正发生的是一个新的临时 Base
是由 client2
生成的,丢弃了 derived
的所有添加成员。这是合法的。编译器不高兴,因为临时 Base
不能用作 base &client1
参数的参数。临时变量就像它们听起来一样。它们的存在时间不长,因此引用一个是编译器阻止您犯的错误。如果它是合法的,临时变量将被 Base
的 >>
运算符修改,然后在您可以使用读入它的内容之前立即超出范围。
in >> (base&) client2;
不分片也不做临时变量。 client2
更新成功。不幸的是,这项工作在
client2=derived(f_name, l_name);
用未初始化的变量覆盖它 l_name
。
因此需要进行更多更改。
不要使用构造函数来完全重新创建和重新分配您正在读入的对象。而是直接读入对象的成员变量。
示例:
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;
}
};
旁注:这是对继承的滥用。这实际上是说姓氏 is-a first name. Which it isn't. Read up on the Liskov Substitution principle for a good rule to help determine when inheritance makes sense. Here's some starter reading: What is an example of the Liskov Substitution Principle?
旁注:>>
将一个空格分隔的标记(一个词)读入给定的 char
数组。这里有两个问题。最重要的是它不知道什么时候停止。 1001 字符数组只能部分缓解这种情况。用户需要长时间键入才能溢出缓冲区,但不要怀疑人们会为了乐趣或利益而这样做。使用 std::string
代替,问题就消失了。第二个问题是整个一个词的事情。此解析器无法处理诸如“Billy Bob”或“von Doom”之类的名称,幸运的是,该姓氏的所有者是虚构的,因为他是众所周知的不宽容。