1

当我试图提高我的 c++ 知识时,我从一个旧的编程竞赛中发现了这个问题。今年我会努力参加比赛,所以我要做好准备。

以下程序的输出是什么?

#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;

}   

这应该在纸上解决,但是因为我是初学者,所以我使用了编译器。此外,变量 counter 和 index 是我添加的,因此我可以跟踪正在创建的对象。原来的表达式是--++v--+++w--;但我用 --++v--+++w 改变了它;因为编译器给了我错误。

那个部分:

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

输出:

  1. 加州索引 1
  2. CB指数1
  3. CC 索引 1
  4. 加州索引 2
  5. 加州索引 3
  6. 加州索引 4
  7. CB指数4

我明白。

我无法理解下一个表达式 --++v--+++w; 所以一开始我试着理解--++v--++的输出;然后我会添加 +w。

--++v--++的输出;是:

  1. 11
  2. 加州索引 5
  3. 乙 10
  4. 加州索引 6
  5. 一个 0 -1
  6. 加州索引 7
  7. C 02
  8. 加州索引 8
  9. DA 指数 6
  10. DA 指数 5

这意味着操作的顺序是--(++((v--)++))。为什么会这样?关于首先评估哪些操作是否有一些规则?另外我不明白为什么要调用索引为 6 和 5 的对象的析构函数?

如果我使用原始表达式,--++v--+++w; ,输出为:

  1. 11
  2. 加州索引 5
  3. 乙 10
  4. 加州索引 6
  5. 一个 0 -1
  6. 加州索引 7
  7. C 02
  8. 加州索引 8
  9. 加法索引 8
  10. DA 指数 6
  11. DA 指数 5

为什么最后评估 +w 操作?是因为运算符优先级吗?另外,我发现如果我写 cout << v.index 它将返回 2,这意味着 v 仍然是之前创建的原始对象。那么索引为 5-8 的对象去哪里了呢?我怎样才能访问它们?

最后一部分,returnClassC(returnClassB(returnClassA(x))); 输出:

  1. 数据库索引 1
  2. DA 指数 1
  3. 数据库索引 1
  4. DA 指数 1
  5. 数据库索引 1
  6. DA 指数 1

我不明白为什么要调用析构函数?

4

1 回答 1

0

一些需要注意的事情当你在 C++ 中重载运算符时,有一些事情需要知道,例如 ++ 你可以做一个预增量

++i

或后增量

i++

为了告诉编译器您正在重载哪个,您需要在签名中没有参数或 int

A operator++(int) 

正在超载帖子增量,

A& operator++() 

重载预增量

在 C++ 中,对象的析构函数在两种情况下被调用

  1. 您对指向使用 new 分配的对象的指针调用 delete

    A* = new A(); //constructor is called
    delete(A);//destructor is called
    
  2. 您为堆栈上创建的对象保留上下文

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

请注意您的代码中一些运算符如何返回一个副本,而另一些则返回一个引用。

A operator++(int) 

这个函数正在返回一个副本。这意味着当您调用此特定函数时,将在函数内部为正在调用的新 A 调用一次构造函数,然后在从函数返回时再次调用 b 指向的对象的副本。

您可以在 [此处] ( http://en.cppreference.com/w/cpp/language/operator_precedence )找到有关运算符优先级的一些信息

我注意到有些人告诉你从这样的代码中学习是没有用的。我同意以这种方式编码非常糟糕,但它可以教会你很多关于构造函数/析构函数、堆/堆栈和运算符如何在 C++ 中工作的知识。可能有更好的学习方法,这对我来说似乎是“期中考试”。

于 2013-04-18T18:21:09.017 回答