Why doesn't the compiler like all the strings that are associated with "Iter"?

97 views Asked by At

I am implementing one of the behavioral design patterns.

The compiler gives errors in lines that are related to "Iter". I don't understand at all why this happens, and even more so, how can it be fixed?

I thought that maybe there was a clerical error somewhere (I'm doing a program following the example from the book, the code is a screenshot and needs to be retyped) - but there is no clerical error, everything is exactly as there.

So what could be the problem?

I suspect it's something simple that is not immediately apparent to me because of my low level of knowledge.

Errors:

main.cpp:57:2: error: ‘Iter’ does not name a type
  Iter* createIterator() const;
  ^~~~
main.cpp:98:41: error: no ‘Iter* ContainerPerson::CreateIterator() const’ member function declared in class ‘ContainerPerson’
 Iter* ContainerPerson::CreateIterator() const {
                                         ^~~~~
main.cpp: In function ‘int main()’:
main.cpp:113:18: error: ‘class ContainerPerson’ has no member named ‘createIterator’
  Iter* it = list.createIterator();
                  ^~~~~~~~~~~~~~
main.cpp:118:10: error: invalid use of non-static member function ‘void Iter::first()’
  for(it->first; !it->isDoneBegin(); it->next()) {
      ~~~~^~~~~
main.cpp:69:7: note: declared here
  void first() {
       ^~~~~
main.cpp:124:10: error: invalid use of non-static member function ‘void Iter::first()’
  for(it->first; !it->isDoneBegin(); it->prev()) {
      ~~~~^~~~~
main.cpp:69:7: note: declared here
  void first() {
       ^~~~~

Full code:

#include <iostream>
#include <string>
using namespace std;

class Person {
public: 
    string name;
    int age;
    string address;

    Person() {
        name = "";
        age = 0;
        address = "";
    }
    
    Person(string n, int a, string ad) {
        name = n;
        age = a;
        address = ad;
    }

    void prn() {
        cout << "Информация о человеке:";
        cout << "\n Фамилия: " << name;
        cout << "\t Возраст: " << age;
        cout << "\n Город: " << address;
    }
};

class ContainerPerson {
public:
    Person* masPerson;
    int currentpos;

    ContainerPerson(int size) {
        masPerson = new Person[size];
        currentpos = - 1;
    }

    ~ContainerPerson() {
        delete []masPerson;
    }

    void add(Person *obj) {
        int pos = ++currentpos;
        masPerson[pos].name = obj->name;
        masPerson[pos].age = obj->age;
        masPerson[pos].address = obj->address;
    }

    bool isEmpty() {
        return (currentpos == - 1);
    }

    friend class Iter;
    Iter* createIterator() const;
};

class Iter {
    const ContainerPerson* container;
    int index;

public:
    Iter(const ContainerPerson* con) {
        container = con;
    }
    
    void first() {
        index = 0;
    }

    void end() {
        index = container->currentpos;
    }

    void next() {
        index++;
    }

    void prev() {
        index--;
    }

    bool isDoneEnd() {
        return (index == container->currentpos + 1);
    }

    bool isDoneBegin() {
        return (index == -1);
    }

    Person currentItem() {
        return container->masPerson[index];
    }
};

Iter* ContainerPerson::CreateIterator() const {
    return new Iter(this);
}

int main() {
    setlocale(LC_ALL, "Russian");
    ContainerPerson list(7);
    list.add(new Person("Sur1", 26, "City1"));  
    list.add(new Person("Sur2", 33, "City2"));
    list.add(new Person("Sur3", 65, "City3"));
    list.add(new Person("Sur4", 43, "City4"));
    list.add(new Person("Sur5", 58, "City5"));
    list.add(new Person("Sur6", 47, "City6"));
    list.add(new Person("Sur7", 32, "City7"));
    
    Iter* it = list.createIterator();
    Person currentPerson;   
    

    cout << "\nOutput (beg-next):";
    for(it->first; !it->isDoneBegin(); it->next()) {
        currentPerson = it->currentItem();
        currentPerson.prn();
    }

    cout << "\nOutput (beg-prev):";
    for(it->first; !it->isDoneBegin(); it->prev()) {
        currentPerson = it->currentItem();
        currentPerson.prn();
    }

    return 0;
}
2

There are 2 answers

3
Nate Eldredge On BEST ANSWER
  1. You need a forward declaration class Iter; outside the declaration of class ContainerPerson. Otherwise the friend class is ContainerPerson::Iter which is unrelated to the Iter you declare later. See Why does a C++ friend class need a forward declaration only in other namespaces?

  2. Typo in the definition of Iter* ContainerPerson::CreateIterator(): should be createIterator, with lower case c.

  3. Typo in for(it->first; ...); should be it->first().

  4. Your iterations are mixed up. They should be

    for(it->first(); !it->isDoneEnd(); it->next()) {
        // ...
    }
    for(it->end(); !it->isDoneBegin(); it->prev()) {
        // ...
    }

With these fixed it compiles and runs cleanly: https://godbolt.org/z/3K7T7d14h

Bonus bug for you to fix later: You never delete the Iter which is allocated in ContainerPerson::createIterator(). That's a memory leak.

0
Vlad from Moscow On
main.cpp:57:2: error: ‘Iter’ does not name a type
  Iter* createIterator() const;
  ^~~~

Though this declaration of a friend class

friend class Iter;

appears in the definition of the class ContainerPerson nevertheless the name Iter is not visible in the scope of the class ContainerPerson.

So the compiler issues an error for this member function declaration.

You need either to declare the class Iter before the class ContainerPerson. For example

class Iter;

class ContainerPerson
{
    //...
    friend class Iter;
    Iter* createIterator() const;
    //...
};

Or to use an elaborated type specifier in the return type in the function declaration like

class ContainerPerson
{
    //...
    friend class Iter;
    class Iter* createIterator() const;
    //...
};


main.cpp:98:41: error: no ‘Iter* ContainerPerson::CreateIterator() const’ member function declared in class ‘ContainerPerson’
 Iter* ContainerPerson::CreateIterator() const {
                                         ^~~~~

You declared the member function

Iter* createIterator() const;
      ^^

not the member function

Iter* CreateIterator() const;
      ^^


main.cpp: In function ‘int main()’:
main.cpp:113:18: error: ‘class ContainerPerson’ has no member named ‘createIterator’
  Iter* it = list.createIterator();
                  ^~~~~~~~~~~~~~

This error is a consequence of the first error.

As for these errors

main.cpp:118:10: error: invalid use of non-static member function ‘void Iter::first()’
  for(it->first; !it->isDoneBegin(); it->next()) {
      ~~~~^~~~~

and

main.cpp:124:10: error: invalid use of non-static member function ‘void Iter::first()’
  for(it->first; !it->isDoneBegin(); it->prev()) {
      ~~~~^~~~~

then it seems you mean a function call

it->first()