西安石油大学期末考试C++真题解析

在这里插入图片描述
1、一、类型、返回值类型 二、参数表、函数重载

2、一、实例化 二、实例化的类型或类类是对象的蓝图,对象是类的实例化

3、const

4、一个 两个

5、一、公有继承 二、私有继承、保护继承

6、抽象类、实例化对象

7、函数模板、类模板

8、try、catch、throw

9、流插入运算符、流提取运算符

10、可以、可以

11、析构函数

程序阅读题:

#include <iostream>
int m = 10;
void a(int n) {
    
    
n = 15 / n;
m = m / 2;
}
int main() {
    
    
int n = 3;
a(n);
std::cout << "m=" << m << std::endl;
std::cout << "n=" << n << std::endl;
return 0;
}

这段代码的功能如下:

  1. 包含了iostream头文件以使用输入输出流。
  2. 定义了一个整型变量m并初始化为10。
  3. 声明了一个函数a,接受一个整型参数n。
  4. 在函数a中,将15除以参数n的值赋给n,然后m除以2的结果赋给m。
  5. 在主函数main中,定义了一个整型变量n并初始化为3。
  6. 调用函数a,并传入参数n。
  7. 使用cout输出m的值,并换行。
  8. 使用cout输出n的值,并换行。
  9. 返回0,表示程序正常结束。
    代码的执行流程如下:
  10. 声明一个整型变量m并初始化为10。
  11. 定义函数a,接受一个整型参数n。
  12. 在函数a中,将15除以参数n的值赋给n,然后将m除以2的结果赋给m。
  13. 在主函数main中,定义一个整型变量n并初始化为3。
  14. 调用函数a,并将参数n的值传入。
  15. 使用cout输出m的值为5,并换行。
  16. 使用cout输出n的值为3,并换行。
  17. 返回0,表示程序正常结束。
    最终输出结果为:
m=5
n=3

这段代码的功能是对变量m和n进行一些计算操作,并输出结果。

答案:m = 5,n = 3; 过程:a(3); ----> { n = 15/3; m = 10/2; } n是在main()函数中声明的,n = 3,所以n = 15/3 = 5,只在函数a()的作用域中n = 5,但是a()是 void 类型,没有返回值,因此,回到main()函数中后,n仍然等于3。而m是全局变量,在整个程序的任何一个地方更改m的值,m的值都将改变,因此a()函数改变m的值后,main()函数中的m的值也发生了相应的改变。所以 ,调用a(3)后,在main()函数中输出cout<<m<<" "<<n<<endl; 结果为: 5 3


#include <iostream>
using namespace std;

class PP {
    
    
    int x, y;
public:
    PP() {
    
    
        x = 3;
        y = 5;
    }
    PP(int i, int j) {
    
    
        x = i - y - j;
    }
    void Messages() {
    
    
        cout << "x=" << x << " y=" << y << endl;
    }
};

int main() {
    
    
    PP* p1 = new PP();
    PP p2(3, 4);
    p2.Messages();
    p1->Messages();
    
    delete p1; // 释放动态分配的内存

    return 0;
}

这段代码的分析过程如下:

  1. 包含了iostream头文件以使用输入输出流。
  2. 使用了using namespace std来避免每次都需要写std::前缀。
  3. 声明了一个名为PP的类。
  4. 在PP类中,定义了私有成员变量x和y。
  5. 提供了两个构造函数:一个无参构造函数,用于初始化x和y的值为3和5;一个有参构造函数,用于将传入的参数分别赋值给x和y。
  6. 定义了一个名为Messages的成员函数,用来输出x和y的值。
  7. 定义了主函数main。
  8. 在主函数中,通过使用new关键字动态地创建了一个PP类的对象p1,并调用了其无参构造函数。这里使用了指针p1来存储对象的地址。
  9. 创建了一个PP类的对象p2,并调用了其有参构造函数,传入参数3和4。对象p2会在栈上分配内存。
  10. 调用p2的Messages函数,输出x和y的值,即输出"x=3 y=4"。
  11. 通过指针p1调用Messages函数,输出x和y的值,即输出"x=3 y=5"。
  12. 使用delete关键字释放动态分配的内存,即释放p1指向的对象的内存。
  13. 返回0,表示程序正常结束。
    最终输出结果为:
x=3 y=4
x=3 y=5

该代码主要展示了类的定义与使用。其中,类PP包含了两个构造函数、两个私有成员变量和一个成员函数。在主函数中,通过对象和指针分别创建并使用了PP类的实例。通过调用成员函数Messages,可以输出对象的成员变量x和y的值。最后,通过delete关键字释放了通过new关键字动态分配的内存,以避免内存泄漏。


分析一下过程#include <iostream>
using namespace std;
class A {
    
    
int a;
public:
A(int aa = 0) : a(aa) {
    
    
cout << a << "    ";
}
~A() {
    
    
cout << "析构";
}
};
int main() {
    
    
A x[2] = {
    
    2};
cout << endl;
return 0;
}

这段代码的分析过程如下:

  1. 包含了iostream头文件以使用输入输出流。
  2. 使用了using namespace std来避免每次都需要写std::前缀。
  3. 声明了一个名为A的类。
  4. 在A类中,定义了一个私有成员变量a。
  5. 提供了一个构造函数A,其中使用了参数的默认值0,用于初始化a的值。构造函数会输出a的值。
  6. 定义了一个析构函数~A,用于在对象被销毁时输出一条提示信息。
  7. 定义了主函数main。
  8. 在主函数中,创建了一个名为x的A类对象数组,数组大小为2。数组中的第一个对象会调用构造函数,并将参数2传入进行初始化。构造函数会输出2。数组中的第二个对象会使用参数的默认值0进行初始化。构造函数会输出0。
  9. 在主函数中,输出一个空行。
  10. 返回0,表示程序正常结束。
    最终输出结果为:
2    0    析构析构

代码的执行过程如下:

  1. 主函数开始执行。
  2. 创建一个名为x的A类对象数组,数组大小为2。
  3. 数组中的第一个对象会调用构造函数A(2),因此构造函数会输出2。
  4. 数组中的第二个对象会使用参数的默认值0进行初始化,因此构造函数会输出0。
  5. 在主函数中,输出一个空行。
  6. 主函数执行完毕,对象数组x会被销毁,先销毁第二个对象(析构函数输出"析构"),再销毁第一个对象(析构函数输出"析构")。
    因此,最终的输出结果是"2 0 析构析构"。(** 析构析构中间没有空!!!**)

#include <iostream>
using namespace std;

class A {
    
    
    int a, b;

public:
    A() {
    
    
        a = 0;
        b = 0;
    }
    A(int m) {
    
    
        a = m;
        b = 0;
    }
    A(int m, int n) {
    
    
        a = m;
        b = n;
    }

    void print() {
    
    
        cout << "a=" << a << " b=" << b << endl;
    }
};

int main() {
    
    
    A a, a2(5), a3(5, 15);

    a.print();
    a2.print();
    a3.print();

    return 0;
}

修正后的代码的运行结果为:

a=0 b=0
a=5 b=0
a=5 b=15

代码的执行过程如下:

  1. 包含了iostream头文件以使用输入输出流。
  2. 使用了using namespace std来避免每次都需要写std::前缀。
  3. 声明了一个名为A的类。
  4. 在A类中,定义了两个私有成员变量a和b。
  5. 提供了三个构造函数:
    • 默认构造函数A(),将a和b都初始化为0。
    • 构造函数A(int m),将a初始化为m,b初始化为0。
    • 构造函数A(int m, int n),将a初始化为m,b初始化为n。
  6. 定义了一个成员函数print(),用于输出a和b的值。
  7. 定义了主函数main。
  8. 在主函数中,分别创建了三个A类对象a、a2和a3,分别使用了不同的构造函数进行初始化。
  9. 依次调用a、a2和a3的print()函数,分别输出a和b的值。
  10. 返回0,表示程序正常结束。
    因此,最终的运行结果为:
a=0 b=0
a=5 b=0
a=5 b=15

#include <iostream>
using namespace std;

class A {
    
    
public:
    A() {
    
    
        cout << "generate class A" << endl;
    }
    ~A() {
    
    
        cout << "destroy class A" << endl;
    }
};

class B : public A {
    
    
public:
    B() {
    
    
        cout << "generate class B" << endl;
    }
    ~B() {
    
    
        cout << "destroy class B" << endl;
    }
};

int main() {
    
    
    B b;

    return 0;
}

这段代码定义了两个类A和B,并在主函数中创建了一个B类对象b。类A和类B都定义了构造函数和析构函数,并且类B继承自类A。
在程序执行过程中,首先创建了一个B类对象b。由于B类是A类的子类,因此在创建B类对象时,会先调用A类的构造函数,然后再调用B类的构造函数。因此,首先输出"generate class A",然后输出"generate class B"。
当程序执行完毕时,会先销毁B类对象b,调用B类的析构函数,输出"destroy class B",然后调用A类的析构函数,输出"destroy class A"。
因此,最终的运行结果为:

generate class A
generate class B
destroy class B
destroy class A

#include <iostream>
using namespace std;
class Base {
    
    
int x;
public:
virtual void Set(int b) {
    
    
x = b;
cout << "x=" << x << endl;
}
};
class Derived : public Base {
    
    
protected:
int y;
public:
void Set(int d) {
    
    
y = d;
cout << "y=" << y << endl;
}
};
int main() {
    
    
Base Bobj;
Derived Dobj;
Base* p;
p = &Bobj;
p->Set(100);
p = &Dobj;
p->Set(200);
return 0;
}

这段代码定义了两个类Base和Derived,并在主函数中创建了一个Base类对象Bobj和一个Derived类对象Dobj。类Base和类Derived都定义了函数Set,并且类Derived继承自类Base。
在程序执行过程中,首先创建了一个Base类对象Bobj和一个Derived类对象Dobj。
接下来,声明了一个Base指针变量p,并将p指向Bobj。然后通过p调用Set(100)函数,由于Set函数是虚函数,所以会根据指针指向的对象类型调用相应的函数。这里p指向的是Base类对象Bobj,所以调用了Base类的Set函数,输出"x=100"。
然后,将p指向Dobj。再次通过p调用Set(200)函数,同样根据指针指向的对象类型调用相应的函数。这里p指向的是Derived类对象Dobj,所以调用了Derived类的Set函数,输出"y=200"。
因此,最终的运行结果为:

x=100
y=200

#include <iostream>
using namespace std;

template <class T>
T min(T x, T y) {
    
    
    cout << "function1: ";
    return (x <= y) ? x : y;
}

int min(int x, int y) {
    
    
    cout << "function2: ";
    return (x < y) ? x : y;
}

int main() {
    
    
    int i = 5, j = 6;
    double d = 1.22, f = 13.21;

    cout << min(i, j) << endl;
    cout << min(d, f) << endl;
    cout << min(d, i) << endl;

    return 0;
}

这段代码定义了一个函数模板min和一个重载的min函数。函数模板min可以接受任意类型的参数,而重载的min函数只接受两个int类型的参数。
在主函数中,创建了两个int类型的变量i和j,并分别初始化为5和6。还创建了两个double类型的变量d和f,并分别初始化为1.22和13.21。
接下来,使用cout输出调用min(i, j)的结果,由于传入的是两个int类型的参数,因此调用的是重载的min函数,输出"function2: 5"。
然后,使用cout输出调用min(d, f)的结果,由于传入的是两个double类型的参数,因此调用的是函数模板min,输出"function1: 1.22"。
最后,使用cout输出调用min(d, i)的结果,由于传入的是一个double类型和一个int类型的参数,因此调用的是函数模板min,输出"function1: 1.22"。
因此,最终的运行结果为:

function2: 5
function1: 1.22
function1: 1.22

#include <iostream>
#include <iomanip>

using namespace std;

int main() {
    
    
    int k = 11;
    cout << "k=" << hex << k << endl;
    float d = 12.34144;
    cout << "d=" << setw(10) << setprecision(5) << setfill('*') << dec<< d << endl;
    
    return 0;
}

给出的代码是正确的。以下是代码的执行过程和运行结果:

  1. 包含了iostream和iomanip头文件以使用输入输出流和格式化输出的函数。
  2. 使用了using namespace std来避免每次都需要写std::前缀。
  3. 定义了主函数main
  4. 声明了一个int类型的变量k,并初始化为11。
  5. 使用cout输出"k=",然后使用hex表示输出k的十六进制形式,输出结果为b。
  6. 声明了一个float类型的变量d,并初始化为12.34144。
  7. 使用cout输出"d=",然后使用setw(10)表示输出宽度为10个字符,使用setprecision(5)表示保留小数点后5位,使用setfill(‘‘)表示填充字符为’’。
  8. 使用dec表示以十进制格式输出。
  9. 最后使用cout输出d的值,输出结果为"*****12.34144"。
    因此,最终的运行结果为:
k=b
d=*****12.34144

#include <iostream>

class A {
    
    
    int x;

public:
    A() {
    
    
        x = 2;
    }

    void print() {
    
    
        std::cout << "x = " << x << std::endl;
    }

    void operator++() {
    
    
        x += 5;
    }

    void operator--() {
    
    
        x -= 2;
    }
};

int main() {
    
    
    A a;
    ++a;
    a.print();
    --a;
    a.print();

    return 0;
}

这段代码定义了一个类 A,并在 main() 函数中使用该类。

A 包含一个私有成员变量 x,默认初始化为 2。类 A 还定义了以下成员函数:

  • print() 函数用于输出变量 x 的值。
  • operator++() 重载了前置递增运算符,将变量 x 的值增加 5。
  • operator--() 重载了前置递减运算符,将变量 x 的值减少 2。

main() 函数中,首先创建了一个类 A 的对象 a,调用构造函数初始化 x 的值为 2。接着,通过 ++ax 的值增加 5,并调用 a.print() 输出结果。然后,通过 --ax 的值减少 2,并再次调用 a.print() 输出结果。

所以,程序的输出结果应为:

x = 7
x = 5

代码逻辑比较简单,它主要演示了对类 A 进行成员函数重载和对对象进行递增和递减操作的功能。


#include <iostream>

class Base {
    
    
    int x, y;

public:
    Base(int x, int y) : x(x), y(y) {
    
    }

    void Move(int m, int n) {
    
    
        x += m;
        y += n;
    }

    void Show() {
    
    
        std::cout << "Base(" << x << "," << y << ")" << std::endl;
    }
};

class Derived : private Base {
    
    
    int x1, yl;

public:
    Derived(int i, int j, int m, int n) : Base(i, j), {x1=m, yl=n;}

    void Show() {
    
    
        std::cout << "Next(" << x1 << "," << yl << ")" << std::endl;
    }

    void Move{Move(2,3);}
     

    void Show1() {
    
    
        Base::Show();
        Show();
    }
};

int main() {
    
    
    Base b(1, 2);
    b.Show();

    Derived d(3, 4, 10, 15);
    d.Move1();
    d.Show();
    d.Show1();
    return 0;
}

这段代码定义了两个类 BaseDerived,并在 main 函数中创建了对象进行测试。

首先,让我们逐行分析代码:

#include <iostream>

这一行代码包含了标准输入输出流库,使得我们可以使用 std::cout 来输出信息。

接下来是类 Base 的定义:

class Base {
    
    
    int x, y;

public:
    Base(int x, int y) : x(x), y(y) {
    
    }

    void Move(int m, int n) {
    
    
        x += m;
        y += n;
    }

    void Show() {
    
    
        std::cout << "Base(" << x << "," << y << ")" << std::endl;
    }
};

Base 有两个私有成员变量 xy,表示整数坐标。构造函数 Base(int x, int y) 用于初始化这两个成员变量。成员函数 Move(int m, int n)xy 分别增加 mn。成员函数 Show() 输出 xy 的值。

接下来是类 Derived 的定义:

class Derived : private Base {
    
    
    int x1, y1;

public:
    Derived(int i, int j, int m, int n) : Base(i, j), x1(m), y1(n) {
    
    }

    void Show() {
    
    
        std::cout << "Next(" << x1 << "," << y1 << ")" << std::endl;
    }

    void Move() {
    
    
        Base::Move(2, 3);
    }

    void ShowAll() {
    
    
        Base::Show();
        Show();
    }
};

Derived 私有继承自 Base,意味着 Derived 类中的成员函数可以访问 Base 类的公有成员函数。类 Derived 有两个私有成员变量 x1y1,表示另外一组整数坐标。构造函数 Derived(int i, int j, int m, int n) 初始化基类 Base 的成员变量,以及派生类 Derived 自己的成员变量。成员函数 Show() 输出派生类的坐标。成员函数 Move() 调用基类 BaseMove() 函数,并传递参数 (2, 3) 来增加 Base 对象的坐标。成员函数 ShowAll() 先调用基类 BaseShow() 函数,然后再调用派生类 DerivedShow() 函数。

最后是 main 函数:

int main() {
    
    
    Base b(1, 2);
    b.Show();

    Derived d(3, 4, 10, 15);
    d.Move();
    d.Show();
    d.ShowAll();

    return 0;
}

main 函数中,首先创建了一个 Base 对象 b,并调用其成员函数 Show() 输出 (1, 2)。接下来,创建了一个 Derived 对象 d,并通过构造函数进行初始化。然后,调用 d.Move() 函数,使得基类 Base 的坐标增加 (2, 3)。接着,调用 d.Show() 输出派生类 Derived 的坐标 (10, 15)。最后,调用 d.ShowAll() 函数,先输出基类 Base 的坐标 (1, 2),然后输出派生类 Derived 的坐标 (10, 15)

根据代码的逻辑,以下是程序运行后的输出结果:

Base(1, 2)
Next(10, 15)
Base(3, 4)
Next(10, 15)

首先,使用 Base 类创建对象 b,然后调用 b.Show() 输出 (1, 2)

接着,使用 Derived 类创建对象 d,并传入参数 (3, 4, 10, 15) 进行初始化。然后,调用 d.Move() 函数,将基类 Base 的坐标增加 (2, 3)

接下来,调用 d.Show() 输出派生类 Derived 的坐标 (10, 15)

最后,调用 d.ShowAll() 函数,先输出基类 Base 的坐标 (3, 4),然后输出派生类 Derived 的坐标 (10, 15)

请注意,由于类 Base 的成员函数 Move()Show() 都没有声明为虚函数,因此在通过基类指针或引用调用这些函数时将无法实现多态性。在这个例子中,直接通过对象调用了相应的函数,而不是通过指针或引用。

程序填空

#include <iostream>

class A {
    
    
public:
——————————————————
    int x, y;

public:
    A(int i, int j) : x(i), y(j) {
    
    }
    
    void Show() {
    
    
        std::cout << "x: " << x << ", y: " << y << std::endl;
    }
};

int main() {
    
    
    A a(1, 2);
    a.Show(); // 调用 Show() 成员函数输出对象的坐标信息
    return 0;
}

程序设计题(共20分)

编写一个输出学校教师和后勒职员信息的程序。设计基类People,属性包括“工号”和“姓名”:派生类教师类Teacher和后勒职员类worker中分别新增属稚“职称”和“工龄”,并设计主函数进行测试。要求:
1,定义构造函数和输出成员函数:
2.使用扩充继承实现派生类人员信息的输出。
根据你的需求,我为你提供了一个满足要求的 C++ 程序示例:

#include <iostream>
#include <string>

// 基类 People
class People {
    
    
protected:
    int id;         // 工号
    std::string name;   // 姓名

public:
    People(int id, const std::string& name)
        : id(id), name(name) {
    
    }

    // 输出成员函数
    void display() const {
    
    
        std::cout << "工号: " << id << std::endl;
        std::cout << "姓名: " << name << std::endl;
    }
};

// 派生类 Teacher
class Teacher : public People {
    
    
private:
    std::string title;  // 职称

public:
    Teacher(int id, const std::string& name, const std::string& title)
        : People(id, name), title(title) {
    
    }

    // 输出成员函数(覆盖基类的 display 函数)
    void display() const {
    
    
        People::display();  // 先调用基类的 display 函数
        std::cout << "职称: " << title << std::endl;
    }
};

// 派生类 Worker
class Worker : public People {
    
    
private:
    int workYears;  // 工龄

public:
    Worker(int id, const std::string& name, int workYears)
        : People(id, name), workYears(workYears) {
    
    }

    // 输出成员函数(覆盖基类的 display 函数)
    void display() const {
    
    
        People::display();  // 先调用基类的 display 函数
        std::cout << "工龄: " << workYears << "年" << std::endl;
    }
};

int main() {
    
    
    People p(1, "张三");
    p.display();
    std::cout << std::endl;

    Teacher t(2, "李四", "教授");
    t.display();
    std::cout << std::endl;

    Worker w(3, "王五", 5);
    w.display();
    std::cout << std::endl;

    return 0;
}

在这个程序中,定义了一个基类 People,以及两个派生类 TeacherWorker,并实现所需的构造函数和输出成员函数。基类 People 包含工号和姓名属性,并提供了 display 函数用于输出成员信息。派生类 TeacherWorker 分别新增了职称和工龄属性,并通过覆盖 display 函数实现了派生类成员信息的输出。

main 函数中,创建了一个基类 People 的对象 p,以及两个派生类对象 TeacherWorker 的对象 tw。分别调用它们的 display 函数,输出各自的成员信息。

程序输出结果为:

工号: 1
姓名: 张三

工号: 2
姓名: 李四
职称: 教授

工号: 3
姓名: 王五
工龄: 5年

当你运行这个程序时,它将创建一个基类 People 的对象 p,并使用构造函数初始化工号为1,姓名为"张三"。然后调用 display 函数输出该对象的成员信息:

工号: 1
姓名: 张三

接下来,程序创建一个派生类 Teacher 的对象 t,并使用构造函数初始化工号为2,姓名为"李四",职称为"教授"。由于 Teacher 类中覆盖了基类 Peopledisplay 函数,所以在调用 t.display() 时会先调用基类的 display 函数,输出工号和姓名,然后再输出职称:

工号: 2
姓名: 李四
职称: 教授

然后,程序创建一个派生类 Worker 的对象 w,并使用构造函数初始化工号为3,姓名为"王五",工龄为5年。同样地,由于 Worker 类中覆盖了基类 Peopledisplay 函数,所以在调用 w.display() 时会先调用基类的 display 函数,输出工号和姓名,然后再输出工龄:

工号: 3
姓名: 王五
工龄: 5年

这样,程序通过扩充继承实现了输出不同类的人员信息,并且派生类中新增的属性也得以正确输出。

这个程序示例展示了面向对象编程中的继承和多态的概念。基类 People 定义了所有人员共有的属性和行为,而派生类 TeacherWorker 在继承基类的同时增加了各自独有的属性,并通过覆盖基类的函数实现了特定的行为。这种设计使得我们可以在统一的接口下操作不同类型的对象,并根据对象的实际类型调用对应的函数。

在这个程序中,我们使用了面向对象编程的三大特性之一:继承。通过继承,派生类可以从基类继承属性和方法,并且可以添加自己的额外属性和方法。这使得我们可以利用代码的复用性,避免重复编写相似的代码。

在示例中,Teacher 类和 Worker 类分别是基类 People 的派生类。它们继承了 People 类中的成员变量 idname,并分别新增了属于自己的成员变量 titleworkYears

为了实现继承,我们使用了 public 访问修饰符来指定派生类对基类成员的访问权限。具体来说,在 Teacher 类和 Worker 类的定义中,我们使用 : public People 将它们声明为公有继承关系。

此外,在 Teacher 类和 Worker 类中,我们还覆盖(override)了基类 People 中的 display 函数。通过使用相同的函数名称和签名,派生类可以重写(override)基类中已经存在的函数,并且通过关键字 override 明确表明这是对基类函数的重写。在派生类中,我们先调用基类的 display 函数,然后再在输出中添加额外的信息,实现了对派生类的特定输出。

这个示例还展示了多态(polymorphism)的概念。多态允许我们通过基类指针或引用来操作派生类对象,以达到统一的接口。在 main 函数中,我们创建了基类 People 的对象 p,以及派生类 TeacherWorker 的对象 tw。然后,我们分别调用它们的 display 函数,尽管它们的类型不同,但由于多态性,它们都会调用正确的成员函数来输出各自的信息。

总结起来,继承和多态是面向对象编程中非常重要的概念。它们提供了代码的组织和重用的机制,使得程序更加灵活和可扩展。通过继承,我们可以构建出更丰富的类层次结构,通过多态,我们可以以统一的方式操作不同类型的对象。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/shaozheng0503/article/details/131466545