【问题标题】:C++ Overloading << Operator problemC++重载<<运算符问题
【发布时间】:2009-10-14 07:44:09
【问题描述】:

我对 C++ 相当陌生,但对指针、取消引用等非常满意。我对类的

#include <string>
#include <iostream>

using namespace std;

class Person
{

private:

 string _name;
 Person* _manager;

public:

 Person(string name, Person *manager);
 Person(string name);

 friend ostream &operator<<(ostream &stream, Person &p);

};


Person::Person(string name, Person *manager)
{
 _name = name;
 _manager = manager;
}

Person::Person(string name)
{
 _name = name;
}

ostream &operator<<(ostream &stream, Person &p)
{
 Person* mgr = p._manager;

 stream << p._name << std::endl;
 stream << mgr->_name << std::endl;
 return stream;
}


int main()
{
 Person *pEmployee = new Person("John Doe Employee");
 Person *pManager = new Person("John Doe Manager", pEmployee);

 cout << *pEmployee;
 cout << *pManager;

 return 0;
}

【问题讨论】:

    标签: c++ pointers operator-overloading


    【解决方案1】:

    在只有一个参数的构造函数中,您需要将 _manager 设置为 NULL/0。在您的 operatorname。就目前而言,您正在取消引用一个未初始化的指针。

    Person::Person(string name)
    {
        _name = name;
        _manager = 0;
    }
    
    ostream &operator<<(ostream &stream, Person &p)
    {
        Person* mgr = p._manager;
    
        stream << p._name << std::endl;
        if (mgr)
            stream << mgr->_name << std::endl;
        return stream;
    }
    

    还有许多其他事情可以做得更好,例如在参数上使用 const 引用和使用构造函数初始化列表,但它们不会成为问题的原因。您还应该解决传递给构造函数的管理器对象的所有权问题,以确保它不会被双重删除。

    【讨论】:

    • 天啊!万分感谢。似乎为时已晚,我忘记了最简单的事情。
    • 既然你在这里:使用初始化列表和默认参数:explicit Person( std::string const &amp; name, Person * manager = 0 ) : _name( name ), _manager(manager) {}。默认参数允许您使用单个参数调用,显式关键字通过使用单个 std::string 构造 Person 来禁用从 std::string 到 Person 的隐式转换
    【解决方案2】:

    你的 _manager 指针在构造第一个 Person 实例时没有初始化,因此在你的操作符

    【讨论】:

    • 在main 方法中使用不带delete 的new 很好。一个main返回,内存被操作系统回收。这里没有内存泄漏。
    • 当然,但是最好将每个新的都与相应的删除匹配;P 但在这种情况下,我宁愿把它全部放在堆栈上。
    【解决方案3】:

    您对operator&lt;&lt; 的实现不会检查_manager 成员是否有效。如果没有经理,您应该通过将指针设置为0 来明确这一点。否则指针值是未定义的,访问它会使你的程序崩溃。

    (1) 如果没有在构造函数中提供,您的Person 类应该将_manager 设置为0(空指针):

    Person::Person(string name) : _name(name), _manager(0)
    {
    }
    

    (2) 在您的operator&lt;&lt; 中,在取消引用之前检查指针:

    if (mgr) {
        stream << mgr->_name << std::endl;
    }
    

    更好的代码的一些提示:

    (1) 将您的函数参数更改为接受const string&amp; 而不是string。这样,在调用函数/构造函数时不会复制字符串,而是作为常量引用传递。

    (2) 让您的operator&lt;&lt; 也接受const 对Person 的引用会更简洁,因为它不会/不应该修改Person。这样,您也可以在有常量Person 的地方使用该运算符。

    【讨论】:

      【解决方案4】:
      Person::Person(string name)
      {
          _name = name;
      }
      

      你的经理是谁?

      Person::Person(string name) : _manager(NULL)
      {
          _name = name;
      }
      
      ostream &operator<<(ostream &stream, Person &p)
      {
       Person* mgr = p._manager;
      
       stream << p._name << std::endl;
       if (mgr != NULL) { stream << mgr->_name << std::endl; }
       return stream;
      }
      

      【讨论】:

        【解决方案5】:

        您的 Person 实例 *pEmployee 没有设置 _manager。这可能是一个 NULL 指针。

        【讨论】:

        • 当他没有明确地将其设置为NULL 时,它不太可能是空指针。 (请注意,我没有没有为此投你反对票:-))
        • 这就是我写 'may' 的原因 ;-) 事实上,悬空指针在 IMO 中要糟糕得多。
        猜你喜欢
        • 2014-04-14
        • 1970-01-01
        • 1970-01-01
        • 2011-03-22
        • 2018-05-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多