面向对象编程例题
A会出现错误。本来我们不写构造函数的话,编译程序会给我们自动加一个,然后A就没错了,但是我们现在写了,编译程序就不会自动加了,如果我们每次创建对象的时候都用两个double进行初始化那也没有问题,但是现在A却想要调用默认构造函数,是不行的会错误;B不能显式地使用构造函数(书上只写了不能在创建之后用显式地用构造函数,这里在创建的时候也不能显式地使用构造函数);C是因为不是指针;D对
输出:ABCCBA,因为对象的析构顺序与构造顺序刚好相反,所以输出ABCCBA而不是ABCABC
4.看下这道题目,如果把代码中的string全部改成char *会怎么样?这个时候注意了,\(h\)被赋值的是指针的地址,而我们每次输入\(s\),都会改变同一地址的值,也就是
所以会导致错误的输出结果
5.对于下面的继承类
class AA
{
public:
AA()
{
cout<<"11";
}
virtual void f()
{
cout<<"AA";
}
};
class BB:public AA
{
public:
BB()
{
cout<<"BB";
}
void f()
{
cout<<"bb";
}
};
class CC:public BB
{
public:
void f()
{
BB::f();
cout<<"CC";
}
};
如果main函数这么写
int main()
{
CC cc;
return 0;
}
那么输出是11BB
,创建cc
的时候,会去调用BB的构造函数,然后BB的构造函数会去调用AA的构造函数输出11
,然后紧接着BB的构造函数会输出BB
如果main函数这么写
int main()
{
AA *p;
BB bb;
p=&bb;
p->f();
return 0;
}
那么输出是11BBbb
,注意这么写所有的f
都是虚函数了,都按照动态绑定算
如果main函数这么些写
int main()
{
AA aa,*p;
BB bb;
CC cc;
p=&cc;
p->f();
return 0;
}
那么输出是1111BB11BBbbCC
可以想一下为什么
如果说最开始类的定义中,CC
的f
函数中没有BB
,那么就相当于函数无限递归,此时调用p->f()
会栈溢出
6.对于下面的函数
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e5+10;
class XX
{
protected:
int k;
public:
XX(int n=5):k(n)
{
}
~XX()
{
cout<<"XX";
}
virtual void f()
{
cout<<k+3;
}
} ;
class YY:public XX
{
public:
~YY()
{
cout<<"YY";
}
void f()
{
cout<<k-3;
XX::f();
}
};
int main()
{
XX &p=*new YY;
p.f();
delete &p;
return 0;
}
输出是28XX
首先解释一下这种新奇的创建动态变量的写法,*
是用来解除引用的,然后右边就不是地址了,而是一个具体的变量,所以可以赋给引用了;最后delete
的时候也必须加上取地址符号
然后解释一下输出,在new
的时候调用YY的构造函数,YY的构造函数调用XX的构造函数将\(k\)变为\(5\),然后调用p.f()
,按照动态绑定调用,最后delete
的时候,析构函数不是虚函数,所以按照静态绑定调用,输出XX
以下程序的输出是
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2e5+10;
class A
{
static int s;
public:
A(int a)
{
s+=a;
}
static void print()
{
cout<<"s="<<s;
}
};
int A::s=0;
int main()
{
A s1(1);A::print();
A s2(2);A::print();
A s3(3);A::print();
return 0;
}