0

親のread()関数を使用して姓名を読み取り、子のread()読み取り専用をミドルネームにすることはできますか? または、子供の最初、2番目、および中間を読む必要がありますか?

編集:最初の答えは機能しているようですが、を使用して子を読み取るとstrtok、3番目のフィールドだけでなく、行全体が取得されます。それを回避する方法はありますか、それとも最初の 2 つのフィールドをダミー変数に読み込んでから、3 番目のフィールドを読み込む必要がありますか?

class Parent
{
protected:
  char first[80], last[80];

  virtual istream& read(istream &is) {
    char temp[80];
    char *f, *l;
    is >> temp;
    f = strtok(temp, ",");
    strcpy(first, f);
    l = strtok(NULL, ",");
    strcpy(last, l);
    return is;
  }

public:
  friend istream& operator>> (istream &is, Parent &parent) {
    return parent.read(is);
  }
};

class Child: public Parent
{
  char middle[80];

  istream& read(istream &is) {
    /*inherit first and last from parent*/
    char temp[80];
    char *m;
    is >> temp;
    m = strtok(temp, ",");
    strcpy(middle, m);
  }
};

in main()

Parent *object;
ifstream inf("filename.csv");
object = new Child();
inf >> *object;

猫ファイル名.csv

George,Bush,Walker
4

3 に答える 3

4

子クラスの関数では、次のように親関数readを呼び出すことができます。read

class Child : public Parent
{
    // ...

    std::istream &read(std::istream &is)
    {
        Parent::read(is);
        // Read some more
    }
};
于 2012-06-05T07:55:46.163 に答える
1

完全な入力を消費するため、子から親の読み取り関数を使用することはできませんParent::read()(文字列に対して NULL-ptr なしで strtok() を実行できるのは、区切り文字を実際に置き換えるため、一度だけです)。注意が必要なのは、Child がストリームの途中から情報を取得する必要があることです。

関数を宣言すれば親の関数を再利用できますreadName()が、これは では簡単に機能しませんstrtok()std::istringstream(strtok を使用する代わりに) 行を入力し、パラメーターとして渡す場所でこれを使用することをお勧めreadName()します。strtok() を使用すると、トークン化を行う prepareRead() を実行してから、strtok(NULL,",") を使用して readName() 関数を読み込むことができますが、これは関数内の副作用に大きく依存します。

エラーケースをコンパイル/テスト/処理していないため、これをコピーして割り当てに貼り付けないでください。

class Parent {
protected:
  std::string first, last;
  std::istringstream readLine(istream& is)
  {
    std::string line;
    std::getline(is, line);
    return std::istringstream(line);
  }
  std::string readName(std::istringstream& iss)
  {
    std::string name;
    std::getline(iss, name, ',');
    return name;
  }

  virtual istream& read(istream &is) 
  {
    std::istringstream iss = readLine(is);
    first = readFirstName(iss);
    last = readLastName(iss);
    return is;
  }
public:
  friend istream& operator>> (istream &is, Parent &parent) 
  {
    return parent.read(is);
  }
};

class Child : public Parent
{
private:
  std::string middle;
  virtual istream& read(istream &is) 
  {
    std::istringstream iss = readLine(is);
    first = readName(iss);
    middle = readName(iss)
    last = readName(iss);
    return is;
  }
};

特に入力では、strcpy を避ける必要があることに注意してください。80 文字を超える名前を含むファイルを渡すと、プログラムが失敗し、ハッキングされる可能性があります。これは、std::string と std::istringstream を使用することで回避できます。

于 2012-06-05T08:42:11.190 に答える
0

1) 親メソッドを として宣言せずvirtual、次のコードを変更します。

class Child: public Parent {
    char middle[80];
    istream& read(istream &is) {
    Parent::read(is);
    char temp[80];
    char *m;
    is >> temp;
    m = strtok(temp, ",");
    strcpy(middle, m); }
};

...を使用しないと、virtual親メソッドは非表示になります。

編集: cppcoderの注意に感謝します。これは間違っていました。次のアプローチを参照してください。

2) またはusing宣言を使用します。これは C++ 標準の例です:

struct A {
    virtual void f();
};

struct B : virtual A {
    virtual void f();
};

struct C : B , virtual A {
    using A::f;
};

void foo() {
    C c;
    c.f(); // calls B::f, the final overrider
    c.C::f(); // calls A::f because of the using-declaration
}
于 2012-06-05T08:02:51.167 に答える