-2

This is the code:

#include<iostream>
#include <cstring>

using namespace std;

class Muncitor
{
    char *nume;
    int vechime;
    static int count;
public:
    Muncitor();
    Muncitor(char *,int);
    friend istream& operator >>(istream &, Muncitor &);
    friend ostream& operator <<(ostream &, const Muncitor &);
    static int afisare_count();
};

int Muncitor::count = 0;

Muncitor::afisare_count()
{
    return count;
}

Muncitor::Muncitor()
{
    this->nume = new char(4);
    strcpy(nume,"Gol");
    this->vechime = 0;
}

Muncitor::Muncitor(char *nume, int vechime)
{
    this->nume = new char(strlen(nume)+1);
    strcpy(this->nume,nume);
    this->vechime = vechime;
    count++;
}

istream& operator >>(istream &is, Muncitor &m)
{
    is.getline(m.nume,100);
    is >> m.vechime;
    return is;
}

ostream& operator <<(ostream &os, const Muncitor &m)
{
    os<<m.nume<<" "<<m.vechime;
    return os;
}

int main()
{
    int n;
    cin>>n;
    Muncitor **a;
    a = new Muncitor*[n];
    for(int i=0;i<n;i++)
    {
        a[i] = new Muncitor;
        cin >> a[i];
    }
    for(int i=0;i<n;i++)
    {
        cout << a[i] << endl;
    }
    cout<<"Count = "<<Muncitor::afisare_count();
}

Here I'm trying to take input, display it, and count how many objects I created. The count should work but for some reason cin >> a[i] does not work. Or I didn't allocate the memory corectly. I don't know. Please help. This is the only way I know how to code so if possible don't give me solutions that use the stl library and such.

samnoon
  • 1,340
  • 2
  • 13
  • 23
Vzlom -
  • 19
  • 5
  • 2
    You are passing in a `Muncitor*` while the function is declared for a `Muncitor&`. Try `cin >> *a[i];` and the same for `cout`. – WhatsUp May 16 '22 at 09:07
  • 1
    Let me guess... you're either coming from Java or C#.... don't use `new` in C++. Usually you don't need raw dynamically allocated objects. Instead use std containers like `std::vector` and `std::string`. – JHBonarius May 16 '22 at 09:20
  • Well I don't know how to use std::vector and std::string so I'd like a solution for my code there. – Vzlom - May 16 '22 at 09:24
  • Maybe there is something wrong with my constructors because if I pass *a[i], after entering the first name it displays 0's for the number of classes I created. – Vzlom - May 16 '22 at 09:26
  • those are core language components, specified in the C++ language standard. You should really learn those if you want to use C++. – JHBonarius May 16 '22 at 09:27
  • @Vzlom- The use of a [good C++ book](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) is highly recommended. – Jason May 16 '22 at 09:28
  • `std::string` is as easy to use as `int` – Caleth May 16 '22 at 09:28
  • P.s. the definition of `Muncitor::afisare_count` should have a return type. Else it's a syntax error. – JHBonarius May 16 '22 at 09:29
  • Read [Why does std::getline() skip input after a formatted extraction?](https://stackoverflow.com/questions/21567291/why-does-stdgetline-skip-input-after-a-formatted-extraction) – molbdnilo May 16 '22 at 10:31
  • The infamous cin.ignore(). Thanks a lot @molbdnilo – Vzlom - May 16 '22 at 19:51

1 Answers1

1

The problem is that a[i] is of type Muncitor* that is, a pointer to a Muncitor object but the second parameter for the overloaded operator>> is a Muncitor& instead of a Muncitor*.

To solve this you can either make sure that you're passing a Muncitor object by dereferencing a[i](like std::cin >>*a[i];) or provide an overload operator>> that has the second parameter as Muncitor*.

Note that you can/should use std::vector.

Method 1

Here the second parameter remains a Muncitor& and we use std::cin>>*a[i]; instead of std::cin>>a[i];.

for(int i=0;i<n;i++)
    {
        a[i] = new Muncitor;
//-------------v-------->note the use of * for dereferencing
        cin >> *a[i];
    }

Demo

Method 2

It is also possible to make the second parameter a Muncitor* and use std::cin>>a[i];, though method 1 above is recommended.

class Muncitor
{
    //other members 
//--------------------------------------------------v--->note the second parameter is a pointer
    friend istream& operator >>(istream &, Muncitor *);
};
//-----------------------------------------v---->note m is a pointer not an lvalue reference 
istream& operator >>(istream &is, Muncitor *m)
{
    //do something here. Also, don't forget to do the null check
    return is;
}

As you can see it is possible to make the second parameter of the overloaded operator>> a pointer type, but it(method 2) is not recommended. Method 1 should be preferred.


Additionally, you forgot to specify the return type int of the static function afisare_count while defining it outside the class. To solve this, you just need to add the return type int while implementing afisare_count as shown below:

//return type int added here
int Muncitor::afisare_count()
{
    return count;
}
Jason
  • 36,170
  • 5
  • 26
  • 60
  • I passed it as a pointer but after the first input it stops. Like I put 2 for the number of classes. I put the first name and then it stops showing me 0's for those 2 classes – Vzlom - May 16 '22 at 09:17
  • While it is *possible* (as you say) to overload `operator>>()` to accept a pointer instead of a reference, it is rarely a good idea to do so (in fact, it is a code smell). In this case, it is a fragile workaround for problems due to using idiomatic techniques from another language (Java, C#, etc) in C++. The better solution is to use idiomatic C++ techniques in C++ rather than idioms from other languages that don't work the same way in C++. (Refer comments below the question concerning use of `new` and use of standard C++ containers). – Peter May 16 '22 at 15:04
  • @Peter Yes, it(overload for pointer) is not recommended as mentioned in my answer(by saying that *"method 1 is recommended"*). I have added one more note in my answer saying that method 2 is not recommended. – Jason May 16 '22 at 15:11