C++ 为什么我能';t调用基类运算符>&燃气轮机;派生类中的运算符>>;?

C++ 为什么我能';t调用基类运算符>&燃气轮机;派生类中的运算符>>;?,c++,class,input,output,overloading,C++,Class,Input,Output,Overloading,假设我们有两个类: class base{ protected: char first_name; public: /// constructors , destructor, operator= overloading ... friend istream& operator >> (istream& in, base &client1) { char f_name[1001];

假设我们有两个类:

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;
    }
};
类基{
受保护的:
字符名;
公众:
///构造函数、析构函数、运算符=重载。。。
friend istream和operator>>(istream和in、base和client1)
{
字符f_名称[1001];
cout>f_名称;
client1=base(f_name);///类参数化构造函数;
返回;
}
};
派生类:公共基{
受保护的:
字符姓氏[1001];
公众:
///构造函数、析构函数、运算符=重载。。。
friend istream和运算符>>(istream和in、派生和客户端2)
{
字符l_名称[1001],f_名称[1001];
在>>(基本)客户端2中;///它的工作方式与运算符>(std::istream&)中的工作方式不同,
abonament)“|”

同样,如果我在派生类运算符内部的运算符中执行相同的操作>>> 为什么会发生这种情况以及如何解决? (我希望我不必在派生类运算符>>中再次重写基类运算符>>中的相同行)

您已经陷入了困境。您可以通过强制转换到引用来解决眼前的问题

真正发生的是,一个新的临时
Base
是由
client2
生成的,丢弃了所有
派生的
添加的成员。这是合法的。编译器会感到不安,因为临时
Base
不能用作
Base&client1
参数的参数。临时变量就像它们的源一样nd.它们并不长,因此引用一个临时变量是编译器阻止您犯的错误。如果它是合法的,则该临时变量将由
Base
运算符修改,然后在您使用读入它的内容之前立即超出范围

in >> (base&) client2;
不切片也不生成临时变量。
client2
已成功更新。不幸的是,当

client2=derived(f_name, l_name);
使用未初始化的变量
l\u 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;
    }
};
类基{
受保护的:
char first_name[1001];//需要多个字符
公众:
///构造函数、析构函数、运算符=重载。。。
friend istream和operator>>(istream和in、base和client1)
{
//char f_name[1001];不需要。读入成员
cout>client1.first\u name;//直接读入成员
//client1=base(f_name);不需要。上述工作已完成
返回;
}
};
派生类:公共基{
受保护的:
字符姓氏[1001];
公众:
///构造函数、析构函数、运算符=重载。。。
friend istream和运算符>>(istream和in、派生和客户端2)
{
//字符l_名称[1001],f_名称[1001];不需要。使用成员变量
在>>(base&)client2;//客户端正在被切片。上面的解释性链接
//^已修复引用以允许多态性
cout>client2.last_name;//修复了拼写错误。直接读取到成员中
//client2=派生的(f_name,l_name);不需要。上面完成的工作
返回;
}
};
旁注:这是对继承的误用。实际上,这意味着姓氏是名。事实并非如此。请阅读Liskov替换原则,了解一个好的规则,以帮助确定继承何时有意义。以下是一些入门读物:


旁注:
>
在给定的
char
数组中读取一个空格分隔的标记,一个单词。这里有两个问题。最重要的是它不知道何时停止。1001字符数组只是部分缓解了这一问题。用户需要长时间键入以溢出缓冲区,但不要怀疑people这样做是为了好玩或赚钱。改用
std::string
,问题就消失了。第二个问题是整个一个单词的问题。这个解析器无法处理像“Billy Bob”或“von Doom”这样的名称“,幸运的是,姓氏的主人是虚构的,因为众所周知他是不宽容的。

char first\u name;
可能会带来悲伤。很少有人有一个字母的名字。警告:
(base)client2;
会。想想看,这可能是你的问题。转换到参考:
(base&)client2;
。我通常强调可复制性,但实际上两者都同样重要。如果你提供了大量代码,你还没有真正尝试隔离问题。如果在给定代码运行时无法复制问题,那么很难正确地检查你的错误并证明提出的答案确实解决了问题。Th它的真正价值在于它是一种强大的调试技术。通常,制作MRE的行为会减少bug周围的噪音,直到在完成MRE之前很久你就可以看到并消除bug。如果你在问题编写过程的早期制作了MRE,你通常可以停止编写问题。
client2=derived(f_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;
    }
};