1:返回什么才好呢
程序填空,使其按要求输出
#include <iostream>
using namespace std;
class A {
public:
int val;
A(int
// 在此处补充你的代码
};
int main()
{
int m,n;
A a;
cout << a.val << endl;
while(cin >> m >> n) {
a.GetObj() = m;
cout << a.val << endl;
a.GetObj() = A(n);
cout << a.val<< endl;
}
return 0;
}
输入
多组数据,每组一行,是整数 m 和 n
输出
先输出一行:
123
然后,对每组数据,输出两行,第一行是m,第二行是n
样例输入
2 3
4 5
样例输出
123
2
3
4
5
代码难点
a.GetObj() = A(n);刚开始对这句话怎么都不理解,现在看来就是this指针的应用,首先a.GetObj()的返回对象为A&类型也就是* this指针,this此时的当前对象为a,这里*this=A(n),表示this->A(n),指向a对象里面的构造函数A(int n)。
答案代码
#include <iostream>
using namespace std;
class A {
public:
int val;
A(int
n)
{
val=n;
}
A()
{
val=123;
}
A& GetObj()
{
return *this;
}
};
int main()
{
int m,n;
A a;
cout << a.val << endl;
while(cin >> m >> n) {
a.GetObj() = m;
cout << a.val << endl;
a.GetObj() = A(n);
cout << a.val<< endl;
}
return 0;
}
2:Big & Base 封闭类问题
程序填空,输出指定结果
#include <iostream>
#include <string>
using namespace std;
class Base {
public:
int k;
Base(int n):k(n) { }
};
class Big
{
public:
int v;
Base b;
// 在此处补充你的代码
};
int main()
{
int n;
while(cin >>n) {
Big a1(n);
Big a2 = a1;
cout << a1.v << "," << a1.b.k << endl;
cout << a2.v << "," << a2.b.k << endl;
}
}
输入
多组数据,每组一行,是一个整数
输出
对每组数据,输出两行,每行把输入的整数打印两遍
样例输入
3
4
样例输出
3,3
3,3
4,4
4,4
代码理解
1. 错误初始化
Big(int n)
{
b=n;
v=n;
}
那么这样写错在哪儿了呢?主要是b=n是一个赋值语句,而在前面Base b;这句话的时候,按理来讲应该用无参的构造函数来声明b,但是我们可以知道在Base类里面,已经有了含参的构造函数,那么编译器就不会提供默认的无参构造函数,于是就会出现编译出错的问题。
正确的写法是:
Big(int n):v(n),b(n) { }
2. 我看到了mian函数里面的
Big a2 = a1;
我就在想这里是不是要来个复制构造函数
Big(const Big& a):b(a)
{
v = a.v;
}
};
但是扭头一想不对,这样成员对象b里面也应该加个复制构造函数,对于这题来说是不对的,这里Big a2 = a1应该调用的是默认复制构造函数,这样就省下很多麻烦,a2和a1就是两个完全相同的成员对象了。
答案代码
#include <iostream>
#include <string>
using namespace std;
class Base {
public:
int k;
Base(int n):k(n) { }
};
class Big
{
public:
int v;
Base b;
Big(int n):b(n)
{
v = n;
}
};
int main()
{
int n;
while(cin >>n) {
Big a1(n);
Big a2 = a1;
cout << a1.v << "," << a1.b.k << endl;
cout << a2.v << "," << a2.b.k << endl;
}
}
3:编程填空:统计动物数量
代码填空,使得程序能够自动统计当前各种动物的数量
#include <iostream>
using namespace std;
// 在此处补充你的代码
void print() {
cout << Animal::number << " animals in the zoo, " << Dog::number << " of them are dogs, " << Cat::number << " of them are cats" << endl;
}
int main() {
print();
Dog d1, d2;
Cat c1;
print();
Dog* d3 = new Dog();
Animal* c2 = new Cat;
Cat* c3 = new Cat;
print();
delete c3;
delete c2;
delete d3;
print();
}
输入
无
输出
0 animals in the zoo, 0 of them are dogs, 0 of them are cats
3 animals in the zoo, 2 of them are dogs, 1 of them are cats
6 animals in the zoo, 3 of them are dogs, 3 of them are cats
3 animals in the zoo, 2 of them are dogs, 1 of them are cats
代码理解
- Animal * c2 = new Cat;// 这里是一个多态,https://wenku.baidu.com/view/aa79f2758e9951e79b89270b.html,这个百度文库写的不错。
Cat c = new Cat(); 实例化一个Cat的对象
Animal a = new Cat();
这代表什么意思呢?
很简单,它表示我定义了一个Animal类型的引用,指向新建的Cat类型的对象。由于Cat是继承自它的父类Animal,所以Animal类型的引用是可以指向Cat类型的对象的。这就是“向上转型”。
那么这样做有什么意义呢?因为子类是对父类的一个改进和扩充,所以一般子类在功能上较父类更强大,属性较父类更独特, 定义一个父类类型的引用指向一个子类的对象既可以使用子类强大的功能,又可以抽取父类的共性。 所以,父类类型的引用可以调用父类中定义的所有属性和方法,而对于子类中定义而父类中没有的方法,父类引用是无法调用的
举例子
1.class Father{
2. public void func1(){
3. func2();
4. }
5. //这是父类中的func2()方法,因为下面的子类中重写了该方法
6. //所以在父类类型的引用中调用时,这个方法将不再有效
7. //取而代之的是将调用子类中重写的func2()方法
8. public void func2(){
9. System.out.println("AAA");
10. }
11.}
12.
13.class Child extends Father{
14. //func1(int i)是对func1()方法的一个重载,主要不是重写!
15. //由于在父类中没有定义这个方法,所以它不能被父类类型的引用调用
16. //所以在下面的main方法中child.func1(68)是不对的
17. public void func1(int i){
18. System.out.println("BBB");
19. }
20. //func2()重写了父类Father中的func2()方法
21. //如果父类类型的引用中调用了func2()方法,那么必然是子类中重写的这个方法
22. public void func2(){
23. System.out.println("CCC");
24. }
25.}
26.
27.public class PolymorphismTest {
28. public static void main(String[] args) {
29. Father child = new Child();
30. child.func1();//打印结果将会是什么?
31. child.func1(68);
32. }
33.}
上面的程序是个很典型的多态的例子。子类Child继承了父类Father,并重载了父类的func1()方法,重写了父类的func2()方法。重载后的func1(int i)和func1()不再是同一个方法,由于父类中没有func1(int i),那么,父类类型的引用child就不能调用func1(int i)方法。而子类重写了func2()方法,那么父类类型的引用child在调用该方法时将会调用子类中重写的func2()。
那么该程序将会打印出什么样的结果呢?
很显然,应该是“CCC”。
Animal * c2 = new Cat;delete c2;由于此处是基类指针指向的派生类,那么在调用析构函数的时候,基类的析构函数必须是虚函数,因为这样才能保证先调用派生类的析构函数,然后调用基类的析构函数,两者不缺。
- 有个问题就是静态变量number既然是全局变量,怎么输出数量时还不一样,基类和派生类的number应该是一样的啊,这个问题后面默默弄懂
答案代码
#include <iostream>
using namespace std;
class Animal
{
public:
static int number;
Animal()
{
number++;
}
virtual ~ Animal()//如果不加virtual,删除c2的时候就不能调用Cat的析构函数了
{
number--;
}
};
class Dog:public Animal
{
public:
static int number;
Dog()
{
number++;
}
~Dog()
{
number--;
}
};
class Cat:public Animal
{
public:
static int number;
Cat()
{
number++;
}
~Cat()
{
number--;
}
};
int Animal::number = 0;//静态成员只能在类外初始化
int Cat::number = 0;
int Dog::number = 0;
void print() {
cout << Animal::number << " animals in the zoo, " << Dog::number << " of them are dogs, " << Cat::number << " of them are cats" << endl;
}
int main() {
print();
Dog d1, d2;
Cat c1;
print();
Dog* d3 = new Dog();
Animal* c2 = new Cat;// 这里是一个多态
Cat* c3 = new Cat;
print();
delete c3;
delete c2;
delete d3;
print();
}
4:这个指针哪来的
填空,按要求输出
#include <iostream>
using namespace std;
struct A
{
int v;
A(int vv):v(vv) { }
// 在此处补充你的代码
};
int main()
{
const A a(10);
const A * p = a.getPointer();
cout << p->v << endl;
return 0;
}
输入
无
输出
10
答案代码
#include <iostream>
using namespace std;
struct A
{
int v;
A(int vv):v(vv) { }
const A * getPointer() const
{
return this;
}
};
int main()
{
const A a(10);
const A * p = a.getPointer();
cout << p->v << endl;
return 0;
}
这题没什么难度,主要是别忘记加const