1

我以为我擅长编程,直到我遇到了我教科书中(很方便地)没有的演练的魔鬼。

我的猜测是关于复制构造函数。

它涉及两个类,ParagraphWord每个Paragraph类中都有一个Word对象的动态数组。问题是当在 main() 中调用Paragraph 类 += 运算符重载方法时 - 教授评论说它调用Word构造函数,然后是Word = 运算符。

如果我错了,请纠正我,但不应该有另一个运算符重载来处理左侧的Word对象和右侧的字符串吗?

#include <iostream>
 using namespace std;
 #define WIDTH 8

 class Word {
     char* text;
     int nletters;
   public:
     Word() {
         text = NULL;
         nletters = 0;
         cout << 'W';
     }
     Word(const char* s) {
         nletters = 0;
         while(s[nletters] != '\0')
             nletters++;
         text = new char[nletters];
         for (int i = 0; i < nletters; i++)
             text[i] = s[i];
         cout << 'X';
     }
     Word(const Word& p) {
         text = NULL;
         *this = p;  // calls assignment operator below
         cout << 'Y';
     }
     ~Word() {
         if (text != NULL) delete [] text;
         cout << "~W" << nletters;
     }
     Word& operator=(const Word& p) {
         if (this != &p) {
             if (text != NULL) delete [] text;
             nletters = 0;
             if (p.text != NULL) {
                 text = new char[p.nletters];
                 while(nletters < p.nletters) {
                     text[nletters] = p.text[nletters];
                     nletters++;
                 }
             }
             else
                 text = NULL;
         }
         cout << 'V';
         return *this;
     }
     int nLetters() const { return nletters; }
     friend ostream& operator<<(ostream& os, const Word& w) {
         if (w.text != NULL)
             for (int i = 0; i < w.nletters; i++)
                 os << w.text[i];
         else
             os << "***";
         os << ' ';
         return os;
     }
 };

 class Paragraph {
     Word* word;
     int mwords;
     int nwords;
     int width;
   public:
     Paragraph() {
         word  = NULL;
         width = WIDTH;
         nwords = 0;
         mwords = 0;
         cout << 'P' << endl;
     }
     Paragraph(const Paragraph& c) {
         word  = NULL;
         *this = c;  // calls assignment operator below
         cout << "cP";
     }
     Paragraph& operator=(const Paragraph& c) {
         if (this != &c) {
             if (word != NULL) delete [] word;
             if (c.word != NULL) {
                 word = new Word[c.mwords];
                 cout << endl;
                 for (int i = 0; i < c.nwords; i++)
                     word[i] = c.word[i];  // calls Word assignment operator
             }
             else
                 word = NULL;
             width  = c.width;
             nwords = c.nwords;
             mwords = c.mwords;
         }
         cout << "=P";
         return *this;
     }
     ~Paragraph() {
         if (word != NULL) delete [] word;
         cout << '\n' << nwords << "~P" << endl;
     }
     void make(int m) {
         if (word == NULL) {
             word = new Word[m];
             mwords = m;
             nwords = 0;
             width  = WIDTH;
         }
     }
     void setWidth(int w) { width = w; }
     friend ostream& operator<<(ostream& os, const Paragraph& p) {
         int nextWord = 0;
         for (int i = 0; i < p.nwords; i++) {
             if (nextWord + p.word[i].nLetters() > p.width) {
                 os << '\n';
                 nextWord = 0;
             }
             cout << p.word[i];
             nextWord += p.word[i].nLetters() + 1;
         }
         return os;
     }
     Paragraph& operator+=(const char* w) {
         if (nwords < mwords) {
             cout << "\n+=";
             word[nwords] = w;  // calls Word constructor, then Word = operator
             nwords++;
         }
         return *this;
     }
 };

 int main() {

     Paragraph p;
     cout << "--------\n";
     p.make(5);
     p += "This";
     p += "is";
     p += "hard";
     cout << "\n--------\n";
     cout << p << endl;
     cout << "--------\n";
     Paragraph q = p;
     q.setWidth(6);
     q += "too";
     cout << "\n--------\n";
     cout << q << endl;
     cout << "---------------\n";
     return 0;
 }
4

1 回答 1

1

你的教授是对的。您不需要另一个运算符,因为 aconst char*可以直接(隐式)转换为 a Word,通过:

Word(const char* s)

这称为转换构造函数。如果将其声明为explicit,则不应再编译。见这里 - http://ideone.com/brjiIi

于是就上线了

word[nwords] = w;

Word确实创建了一个临时对象w,然后Word调用赋值运算符 for 将临时对象分配给words[nwords]

关于代码的其他一些注释:

  • 既然你的教授教你 C++,你应该学习std::stringstd::vector. 他不需要 C++ 或类来展示指针或动态内存分配的强大功能。
  • 像这样的陈述if (word != NULL) delete [] word;是多余的。deletedelete[]NULL指针上保证工作(而不做任何事情)。
  • 构造函数中的逻辑是错误的(如果你自己没有管理内存就不会)。在您构造 a 之后Paragraph,在您调用 之前它是不可用的make(),这是糟糕的设计。
于 2012-08-16T01:22:02.287 回答