سؤال

While I was trying to improve my c++ knowledge, I found this problem from an old programming contest. I will try to enter the contest this year so I want to be prepared.

What is the output for the following program?

#include <iostream>

using namespace std;

int dat=1;
int counter=0;

class ClassB;

class B {

  public: 
          virtual void f(int d=5)=0;
          };

class A {

  unsigned i;
  public:
         int pod;
         int index;


         A& operator++() { cout<<"A "<<pod--<<dat++<<endl; A* b=new A;  return *b; }
         A operator++(int) {cout<<"B "<<pod++<<dat--<<endl; A* b=new A;  return *b;}
         A& operator--() {cout<<"C "<<dat++ <<++pod<<endl; A* b=new A;  return *b;}
         A operator--(int) {cout<<"D "<<dat--<<--pod<<endl; A* b=new A;  return *b;}
         void operator+(A& b) {cout<<"Addition Index "<<index<<endl; pod++;}

         friend void B::f(int);
         A() : i(0), pod(dat) {pod++; index=++counter; cout<<"CA "<<"Index "<<index<<endl; }
         ~A(){pod++; cout<<"DA Index "<<index<<endl;}

};              


 const ClassB& returnClassA(const ClassB& p) {return p;}


class ClassB: public A, public B {
    public:
         void f(int d=2){A c; c++; pod*=d--;}
         ClassB(){cout<<"CB Index "<<index<<endl;}
         ~ClassB(){cout<<"DB Index "<<index<<endl;}
};


ClassB returnClassB(ClassB s) {return s;}

class ClassC : public ClassB {
  public:
         ClassC(){cout<<"CC Index "<<index<<endl;}
         ~ClassC(){cout<<"DC Index "<<index<<endl;}
};

ClassB returnClassC(ClassB s){return s;}

int main()
{           
    ClassC x;      
    A v,w;               
    B *c = new ClassB;   

   --++v--+++w;

   returnClassC(returnClassB(returnClassA(x))); 

   return 0;

}   

This is supposed to be solved on paper, but because I am beginner I used compiler. Also, the variables counter and index were added by me so I can keep track of the objects that are being created. The original expression was --++v--+++w--; but I changed it with --++v--+++w; because the compiler was giving me errors.

The part:

ClassC x;      
A v,w;               
B *c = new ClassB;

outputs :

  1. CA Index 1
  2. CB Index 1
  3. CC Index 1
  4. CA Index 2
  5. CA Index 3
  6. CA Index 4
  7. CB Index 4

Which I understand.

I have problem understanding the next expression, --++v--+++w; so at first I tried understanding the output of --++v--++; and then I would add +w.

The output of --++v--++; is:

  1. D 11
  2. CA Index 5
  3. B 10
  4. CA Index 6
  5. A 0 -1
  6. CA Index 7
  7. C 02
  8. CA Index 8
  9. DA Index 6
  10. DA Index 5

This means that the order of the operations is --(++((v--)++)). Why is this so? Is there some rule as to which operations are evaluated first? Also I don't understand why the destructors of the objects with Index 6 and 5 are called?

If I use the original expression, --++v--+++w; , the output is:

  1. D 11
  2. CA Index 5
  3. B 10
  4. CA Index 6
  5. A 0 -1
  6. CA Index 7
  7. C 02
  8. CA Index 8
  9. Addition Index 8
  10. DA Index 6
  11. DA Index 5

Why the +w operation is evaluated last? Is it because of the operator precedence? Also, I found out that if I write cout << v.index it would return 2, meaning v is still the original object created before. So where do the objects with indexes 5-8 go? How can I access them?

The last part, returnClassC(returnClassB(returnClassA(x))); outputs:

  1. DB Index 1
  2. DA Index 1
  3. DB Index 1
  4. DA Index 1
  5. DB Index 1
  6. DA Index 1

I don't understand why the destructors are called?

هل كانت مفيدة؟

المحلول

A few things to note When you are overloading operators in C++ there are some things to know, for example ++ you caneither do a preincrement

++i

or a post increment

i++

in order to tell the compiler which you are overloading you'll need to have no parameters or an int in the signature

A operator++(int) 

is overloading the post incremennt,

A& operator++() 

overloads pre increment

In C++ an object's desctructor is called in two cases

  1. You call delete on a pointer to an object you allocated using new

    A* = new A(); //constructor is called
    delete(A);//destructor is called
    
  2. You leave context for an object created on the stack

    if(something) {
        A a();
        ...
    } //here a's destructor is called because a no longer exists
    

Notice in your code how some operators return a copy, others return a reference.

A operator++(int) 

this function is returning a copy. This means that when you call this particular function the constructor is being called once inside the function for the new A that is being called and then again when you return from the function as a copy of the object pointed to by b is being copied.

You can find some infromation on operator precedence [here] (http://en.cppreference.com/w/cpp/language/operator_precedence)

I notice some people are tellign you it's useless to learn from code like this. I agree that coding in this way is pretty bad, but it can teach you a lot about how constructors/destructors, heap/stack and operators work in C++. There are probably better ways of learning, this seems pretty 'mid-term examy' to me.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top