在我努力提高我的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;
}
这应该在纸上解决,但因为我是初学者,所以我使用了编译器。 此外,我添加了变量计数器和索引,因此我可以跟踪正在创建的对象。最初的表达是 - ++ v - +++ w--;但是我改为 - ++ v - +++ w;因为编译器给了我错误。
部分:
ClassC x;
A v,w;
B *c = new ClassB;
输出:
我理解。
我有理解下一个表达式的问题, - ++ v - +++ w;所以一开始我试着理解 - ++ v - ++的输出;然后我会添加+ w。
- ++ v - ++的输出;是:
这意味着操作的顺序是 - (++((v - )++))。 为什么会这样?是否有一些关于首先评估哪些操作的规则? 另外我不明白为什么调用索引6和5的对象的析构函数?
如果我使用原始表达式, - ++ v - +++ w; , 输出是:
为什么最后评估+ w操作?是因为运营商优先吗? 另外,我发现如果我写cout&lt;&lt; v.index它将返回2,这意味着v仍然是之前创建的原始对象。那么索引5-8的对象去哪里了?我该如何访问它们?
最后一部分,returnClassC(returnClassB(returnClassA(x))); 输出:
我不明白为什么要调用析构函数?
答案 0 :(得分:0)
有几点需要注意 当你在C ++中重载运算符时,有一些事情需要知道,例如++你可以做一个preincrement
++i
或后增量
i++
为了告诉编译器你正在重载,你需要在签名中没有参数或int
A operator++(int)
正在重载帖子增量,
A& operator++()
重载预增量
在C ++中,在两种情况下调用对象的析构函数
在指向使用新
分配的对象的指针上调用deleteA* = new A(); //constructor is called
delete(A);//destructor is called
您为堆栈上创建的对象保留上下文
if(something) {
A a();
...
} //here a's destructor is called because a no longer exists
请注意,在您的代码中,某些运算符如何返回副本,其他运算符则返回引用。
A operator++(int)
此函数返回一份副本。这意味着当您调用此特定函数时,构造函数将在函数内部被调用一次,该函数将被调用,然后再次从函数返回时,正在复制b指向的对象的副本。 / p>
您可以在运算符优先级[here](http://en.cppreference.com/w/cpp/language/operator_precedence)
中找到一些信息我注意到有些人告诉你,从这样的代码中学习是没用的。我同意以这种方式编码非常糟糕,但它可以教你很多关于构造函数/析构函数,堆/堆栈和运算符如何在C ++中工作。可能有更好的学习方式,这对我来说似乎是“中期考试”。