0

我可以使用父read()函数读取名字和姓氏,然后让孩子read()读取中间名吗?或者我必须在孩子身上阅读第一,第二和中间?

编辑:第一个答案似乎有效,但是当我在 child using 中阅读时strtok,我得到了整行,而不仅仅是第三个字段。有没有办法解决它,或者我只需要将前两个字段读入虚拟变量,然后再读取第三个字段?

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

您不能从 Child 使用 Parent 的 read 函数,因为Parent::read()它会消耗完整的输入(您只能对字符串执行一次没有 NULL-ptr 的 strtok() ,因为它实际上替换了分隔符)。棘手的部分是 Child 必须从流的中间获取信息。

如果您声明一个readName()函数,您可以重用 Parent 的函数,但这不适用于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 回答