西安石油大学 C++期末考试 重点知识点+题目复习(下)

news2024/11/17 5:33:30

析构函数调用顺序

析构函数的调用顺序与对象的创建和销毁顺序相反。

对于单个对象,当对象的生命周期结束时(例如离开作用域),会调用其析构函数。因此,析构函数会在对象销毁之前被调用。

对于类的成员对象,它们的析构函数的调用顺序与它们在类中的声明顺序相反。即,在类的析构函数中,首先会调用最后一个声明的成员对象的析构函数,然后依次调用上一个成员对象的析构函数,直到第一个声明的成员对象的析构函数被调用。

下面是一个示例代码,演示了析构函数的调用顺序:

#include <iostream>

class A {
public:
    A() { std::cout << "A's constructor" << std::endl; }
    ~A() { std::cout << "A's destructor" << std::endl; }
};

class B {
public:
    B() { std::cout << "B's constructor" << std::endl; }
    ~B() { std::cout << "B's destructor" << std::endl; }
};

class C {
    A a;
    B b;

public:
    C() { std::cout << "C's constructor" << std::endl; }
    ~C() { std::cout << "C's destructor" << std::endl; }
};

int main() {
    C c;
    return 0;
}

输出结果将是:

A's constructor
B's constructor
C's constructor
C's destructor
B's destructor
A's destructor

这里,C 类包含了 A 类和 B 类的成员对象。在主函数中创建 C 类的对象 c 时,会按照逆序调用析构函数,即先调用 C 类的析构函数,然后调用 B 类的析构函数,最后调用 A 类的析构函数。

当涉及到类继承关系时,在析构函数的调用顺序中会有一些特殊情况需要考虑。

  1. 基类和派生类的析构函数调用顺序:

    • 当派生类对象的生命周期结束时,首先会调用派生类自身的析构函数。
    • 然后,会自动调用基类的析构函数。
    • 这是因为在派生类的析构函数中,默认会自动调用基类的析构函数以确保派生类对象的所有父类部分都会正确析构。
  2. 虚析构函数的调用顺序:

    • 如果基类的析构函数被声明为虚函数(通过在基类的析构函数前加上 virtual 关键字),则在删除指向派生类对象的基类指针时,会按照派生类到基类的顺序依次调用析构函数。
    • 这种情况下,通过基类指针删除对象时,会使用动态绑定将析构函数调用转发到派生类的析构函数。

下面是一个示例代码,演示了带有继承关系的类的析构函数调用顺序和虚析构函数的应用:

#include <iostream>

class Base {
public:
    Base() { std::cout << "Base's constructor" << std::endl; }
    virtual ~Base() { std::cout << "Base's destructor" << std::endl; }
};

class Derived : public Base {
public:
    Derived() { std::cout << "Derived's constructor" << std::endl; }
    ~Derived() { std::cout << "Derived's destructor" << std::endl; }
};

int main() {
    Base* ptr = new Derived();
    delete ptr;
    return 0;
}

输出结果将是:

Base's constructor
Derived's constructor
Derived's destructor
Base's destructor

在这个示例中,Derived 类继承了 Base 类。通过创建一个指向 Derived 类对象的 Base 类指针,然后通过该指针删除对象,我们可以观察到析构函数的调用顺序。

在删除指针时,先调用派生类 Derived 的析构函数,然后自动调用基类 Base 的析构函数。

在这里插入图片描述

C++中异常处理的抛出代码示例+讲解

异常处理的 try-catch 机制可以用于捕获和处理程序中的异常情况。下面是一个示例代码,演示了如何使用 try-catch 来处理异常:

#include <iostream>
#include <stdexcept>

double divide(double dividend, double divisor) {
    if (divisor == 0.0) {
        throw std::runtime_error("Error: Division by zero!");
    }
    
    return dividend / divisor;
}

int main() {
    double a = 10.0;
    double b = 0.0;
    
    try {
        double result = divide(a, b);
        std::cout << "Result: " << result << std::endl;
    } catch (const std::exception& e) {
        std::cerr << "Exception caught: " << e.what() << std::endl;
    }
    
    return 0;
}

在这个示例中,我们定义了一个 divide() 函数来计算两个数的商。如果除数为零,我们使用 throw 关键字抛出一个标准库的 runtime_error 异常,并提供错误消息。

在主函数中,我们声明了两个变量 ab,并将 b 设置为零。然后,我们使用 try 块来执行 divide(a, b),并使用 catch 块来捕获异常。在 catch 块中,我们使用 std::exception 类型的引用来捕获可能发生的异常,并通过 e.what() 获取异常的错误消息。最后,我们输出错误消息到标准错误流。

运行程序,得到以下输出:

Exception caught: Error: Division by zero!

在这个示例中,当除数为零时,我们抛出了一个 runtime_error 异常。在 catch 块中,我们捕获了这个异常,并输出了错误消息。

需要注意的是,在实际开发中,我们可以根据业务需求定义自己的异常类,并根据具体情况来选择不同的异常类型进行抛出和捕获。

文件输入输出

输入和输出
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1IcKv2tN-1688091249591)(2023-06-20-20-53-48.png)]
与输入输出流操作相关的类有很多,以下是一些常见的:

  1. std::ifstream / std::ofstream:用于读取和写入文件。
  2. std::stringstream / std::ostringstream:用于将字符串作为流来处理。
  3. std::cin / std::cout:用于输入和输出标准输入输出流。
  4. std::wifstream / std::wofstream:用于读取和写入宽字符文件。
  5. std::istringstream / std::ostringstream:用于将字符串流化为输入输出流。
  6. std::wstringstream / std::wostringstream:用于将 wchar_t 类型字符串转化为输入输出流。

以上这些类都是基于标准输入输出流 std::stream 的派生类,使用这些类的时候需要包含 头文件。在使用这些类时,通常需要注意打开和关闭文件、读写字符或字符串的方式等操作。同时,需要注意数据的编码方式,例如 ASCII 码和 Unicode 码等,以确保数据的正确读写和传输。

输入和输出
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-znl2t5Xs-1688091290386)(2023-06-20-20-53-48.png)]
与输入输出流操作相关的类有很多,以下是一些常见的:

  1. std::ifstream / std::ofstream:用于读取和写入文件。
  2. std::stringstream / std::ostringstream:用于将字符串作为流来处理。
  3. std::cin / std::cout:用于输入和输出标准输入输出流。
  4. std::wifstream / std::wofstream:用于读取和写入宽字符文件。
  5. std::istringstream / std::ostringstream:用于将字符串流化为输入输出流。
  6. std::wstringstream / std::wostringstream:用于将 wchar_t 类型字符串转化为输入输出流。

以上这些类都是基于标准输入输出流 std::stream 的派生类,使用这些类的时候需要包含 头文件。在使用这些类时,通常需要注意打开和关闭文件、读写字符或字符串的方式等操作。同时,需要注意数据的编码方式,例如 ASCII 码和 Unicode 码等,以确保数据的正确读写和传输。

除了使用std::fstream类打开文件外,还有其他几种方式可以在C++中打开文件。以下是两种常用的方式:

  1. 使用C风格的文件操作函数:
    你可以使用C标准库中的文件操作函数,如fopen()fread()fwrite()fclose()等来打开和处理文件。这种方式需要包含<cstdio>头文件。下面是一个示例代码:

    #include <cstdio>
    
    int main() {
        FILE* file = std::fopen("example.txt", "r");
        if (file != nullptr) {
            char buffer[256];
            while (std::fgets(buffer, sizeof(buffer), file)) {
                std::puts(buffer);
            }
            std::fclose(file);
        } else {
            std::perror("Failed to open file.");
        }
    
        return 0;
    }
    

    在这个示例中,我们使用std::fopen()函数打开名为 “example.txt” 的文件,并指定模式为 “r”(只读)。如果成功打开文件,则进入一个循环,使用std::fgets()函数逐行读取文件内容,并将每行输出到标准输出流(控制台)上。

    最后,我们使用std::fclose()函数关闭文件指针。如果文件打开失败,则使用std::perror()函数输出错误消息。

  2. 使用第三方库:
    除了C++标准库提供的文件操作功能,你还可以使用第三方库来简化文件操作。例如,常用的库包括 Boost.Filesystem和 std::filesystem(C++17标准引入)。

    使用这些库可以提供更高级的文件操作功能,如遍历目录、文件复制和删除等。具体使用方式可以参考相关库的文档和示例代码。

无论你选择哪种方式打开文件,都应该在操作完成后及时关闭文件流或释放相应的资源,以避免资源泄漏。

三种继承方式+代码示例

C++中有三种继承方式,分别是公有继承(public inheritance)、私有继承(private inheritance)和保护继承(protected inheritance)。

下面分别给出这三种继承方式的代码示例:

1. 公有继承(public inheritance):

#include <iostream>

using namespace std;

// 基类
class Base {
public:
    void print() {
        cout << "This is the base class." << endl;
    }
};

// 派生类
class Derived : public Base {
public:
    void display() {
        cout << "This is the derived class." << endl;
    }
};

int main() {
    Derived d;
    d.print();    // 可以访问基类的公有成员函数
    d.display();  // 可以访问派生类自身的成员函数
    return 0;
}

这里派生类Derived公有继承自基类Base,因此派生类可以访问基类的公有成员函数。

2. 私有继承(private inheritance):

#include <iostream>

using namespace std;

// 基类
class Base {
public:
    void print() {
        cout << "This is the base class." << endl;
    }
};

// 派生类
class Derived : private Base {
public:
    void display() {
        cout << "This is the derived class." << endl;
    }
};

int main() {
    Derived d;
    // d.print();  // 错误,无法访问基类的公有成员函数,因为私有继承使得基类的成员在派生类内部变为私有成员
    d.display();  // 可以访问派生类自身的成员函数
    return 0;
}

这里派生类Derived私有继承自基类Base,因此基类的公有成员函数在派生类内部变为私有成员。私有继承意味着派生类不能直接访问基类的公有和受保护成员,只能通过派生类自身的成员函数来间接访问。

3. 保护继承(protected inheritance):

#include <iostream>

using namespace std;

// 基类
class Base {
protected:
    void print() {
        cout << "This is the base class." << endl;
    }
};

// 派生类
class Derived : protected Base {
public:
    void display() {
        cout << "This is the derived class." << endl;
    }
};

int main() {
    Derived d;
    // d.print();  // 错误,无法访问基类的受保护成员函数,因为保护继承使得基类的成员在派生类内部变为受保护成员
    d.display();  // 可以访问派生类自身的成员函数
    return 0;
}

这里派生类Derived保护继承自基类Base,因此基类的公有成员函数在派生类内部变为受保护成员。保护继承意味着派生类可以直接访问基类的受保护成员,但不能访问基类的公有成员。

c++中的格式控制符

在C++中,格式控制符用于定义输入和输出的格式。它们可以控制数据的显示方式、精度、对齐方式等。以下是一些常见的C++格式控制符:

  1. 基本的格式控制符:

    • %d:用于输出有符号十进制整数。
    • %u:用于输出无符号十进制整数。
    • %f:用于输出浮点数。
    • %c:用于输出字符。
    • %s:用于输出字符串。
    • %p:用于输出指针的地址。
  2. 修饰符和标志位:

    • %5d:表示输出宽度为5个字符的有符号十进制整数,如果不足5个字符则用空格填充。
    • %.2f:表示输出浮点数的小数部分保留两位。
    • %+d:用于输出带正负号的有符号十进制整数。
    • %#x:用于输出十六进制数,并添加前缀 “0x”。
    • %03d:表示输出宽度为3个字符的有符号十进制整数,不足3个字符用零填充。
    • %10s:表示输出宽度为10个字符的字符串,如果不足10个字符则用空格填充。
    • %*d:用于动态指定输出宽度的有符号十进制整数。
  3. 控制输出对齐:

    • %10d:表示输出宽度为10个字符的有符号十进制整数,右对齐,默认情况下左对齐。
    • %-10s:表示输出宽度为10个字符的字符串,左对齐,默认情况下右对齐。
  4. 控制输入格式:

    • %d:用于读取有符号十进制整数。
    • %f:用于读取浮点数。
    • %c:用于读取字符。
    • %s:用于读取字符串。

以上只是一些常见的格式控制符示例,实际上C++中还有更多的格式控制符和选项可供使用。你可以根据具体需求选择适合的格式控制符来处理输入和输出。

课后习题:

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

编写一个时间类,采用运算符重载的方法实现时间的加、减运算,以及时间的显示。编写主函数进行测试。

下面是一个示例的时间类,实现了运算符重载来进行时间的加减运算和显示:

#include <iostream>

class Time {
private:
    int hours;
    int minutes;
public:
    Time(int h = 0, int m = 0) : hours(h), minutes(m) {}

    Time operator+(const Time& other) const {
        int h = hours + other.hours;
        int m = minutes + other.minutes;
        if (m >= 60) {
            h += m / 60;
            m %= 60;
        }
        return Time(h, m);
    }

    Time operator-(const Time& other) const {
        int h = hours - other.hours;
        int m = minutes - other.minutes;
        if (m < 0) {
            h -= 1;
            m += 60;
        }
        return Time(h, m);
    }

    void display() const {
        std::cout << hours << " hours, " << minutes << " minutes" << std::endl;
    }
};

int main() {
    Time t1(2, 30);
    Time t2(1, 45);
    Time t3 = t1 + t2;
    Time t4 = t1 - t2;

    std::cout << "t1: ";
    t1.display();
    std::cout << "t2: ";
    t2.display();
    std::cout << "t1 + t2: ";
    t3.display();
    std::cout << "t1 - t2: ";
    t4.display();

    return 0;
}

输出结果将是:

t1: 2 hours, 30 minutes
t2: 1 hours, 45 minutes
t1 + t2: 4 hours, 15 minutes
t1 - t2: 0 hours, 45 minutes

在这个示例中,我们定义了一个时间类 Time,它具有小时(hours)和分钟(minutes)两个私有成员变量。然后我们重载了加法运算符(+)和减法运算符(-),通过计算小时和分钟来实现时间的加减运算。同时,我们还提供了一个显示函数 display() 来将时间输出到标准输出流。

在主函数中,我们创建了两个时间对象 t1t2,并进行了加法和减法运算,将结果保存到 t3t4 中,然后分别使用 display() 函数显示了每个时间对象的值。

设计一个基本帐户类

设计一个基本帐户类,通过继承设计一个储蓄帐户类。在储蓄帐户类中增加一个静态成员变量年利率,并增加成员函数:

(1)计算月利息;

(2)更改年利率。

编写主程序进行测试,并上传程序运行结果

下面是一个示例的基本账户类和储蓄账户类,包括静态成员变量年利率和相关函数的实现:

#include <iostream>

class Account {
protected:
    double balance;
public:
    Account(double init_balance = 0) : balance(init_balance) {}

    virtual void display() const {
        std::cout << "Account balance: $" << balance << std::endl;
    }

    virtual ~Account() {}
};

class SavingsAccount : public Account {
private:
    static double annual_interest_rate;
public:
    SavingsAccount(double init_balance = 0) : Account(init_balance) {}

    void calculate_monthly_interest() const {
        double monthly_interest = balance * (annual_interest_rate / 12);
        std::cout << "Monthly interest: $" << monthly_interest << std::endl;
    }

    static void set_interest_rate(double rate) {
        annual_interest_rate = rate;
    }

    void display() const override {
        Account::display();
        std::cout << "Annual interest rate: " << annual_interest_rate * 100 << "%" << std::endl;
    }
};

double SavingsAccount::annual_interest_rate = 0;

int main() {
    SavingsAccount sa(1000);
    sa.set_interest_rate(0.05);

    sa.display();
    sa.calculate_monthly_interest();

    return 0;
}

输出结果将是:

Account balance: $1000
Annual interest rate: 5%
Monthly interest: $4.16667

在这个示例中,我们首先定义了一个基本账户类 Account,它有一个受保护的成员变量 balance 表示账户余额。然后,我们派生出一个储蓄账户类 SavingsAccount,并添加了一个静态成员变量 annual_interest_rate 表示年利率。

SavingsAccount 类中,我们实现了两个成员函数。calculate_monthly_interest() 函数用于计算月利息,根据余额和年利率计算得出。set_interest_rate() 函数用于更改年利率的值。

在主函数中,我们创建了一个储蓄账户对象 sa,并设置了年利率为 0.05。然后使用 display() 函数显示账户信息,包括余额和年利率,并调用 calculate_monthly_interest() 函数计算月利息。

#include <iostream>
#include <cstring >
using namespace std;

class Account {
	public:
		Account(char name[], long num, float amount); 	//类的有参构造函数
		Account(); 										//类的无参构造函数
		void deposit(float amount);			//往当前账户中存款
		int withdraw(float amount);			//从当前账户中取款
		float getBalance(); 				//查询当前账户的余额
	private:
		char mName[20]; 			//银行账户的户名
		long mSN; 					//本账户的帐号
		float mBalance; 			//本账户当前的余额
};

//类的有参构造函数
Account::Account(char name[], long num, float amount) {
	strcpy(mName, name);      //字符串复制函数
	mSN = num;
	mBalance = amount;
}

//类的无参构造函数
Account::Account() {
	cout << "无参函数被调用!" << endl;
}

//往当前账户中存款
void Account::deposit(float amount) {
	mBalance = mBalance + amount;
}

//从当前账户中取款
int Account::withdraw(float amount) {
	if (amount > mBalance) {
		return 0;
	} else if (amount <= mBalance) {
		mBalance = mBalance - amount;
		return 1;              //return 1代表函数非正常终止
	}
}

//查询当前账户的余额
float Account::getBalance() {
	return mBalance;
}

//主函数
int main() {
	int NO, m;
	char name[20];
	long num;
	float amount;
	cout << "请输入所开账户户名:";
	cin >> name;
	cout << "请输入所开账户帐号:";
	cin >> num;
	cout << "请输入所开账户初始存款金额:";
	cin >> amount;
	Account A(name, num, amount);
	cout << "" << endl;
	cout << "------------------------------------------------" << endl;
	cout << "                   菜单栏                       " << endl;
	cout << "1、存款请输入“1”" << endl;
	cout << "" << endl;
	cout << "2、取款请输入“2”" << endl;
	cout << "" << endl;
	cout << "3、查询账户余额请输入“3”" << endl;
	cout << "" << endl;
	cout << "4、退出请输入“4”" << endl;
	cout << "" << endl;
	cout << "------------------------------------------------" << endl;
	while (1) {
		cout << "请输入选择:" << endl;
		cin >> NO;
		switch (NO) {       //通过switch循环来判断输入的菜单栏选择对应其相应的操作
			case 1:
				cout << "请输入存款金额:";
				cin >> amount;
				A.deposit(amount);
				break;								//表示跳出该switch语句体
			case 2:
				cout << "请输入取款金额:";
				cin >> amount;
				m = A.withdraw(amount);
				if (m == 0)
					cout << "当前账户余额不足!" << endl;
				else
					cout << "取款成功!" << endl;
				break;
			case 3:
				cout << "当前账户余额为:" << A.getBalance() << endl;
				break;
			case 4:
				cout << "账户已退出!" << endl;
				return 0;
			default:
				cout << "输入错误!" << endl;			//判断输入菜单栏是否输入正确
				exit(0);
		}
		cout << "" << endl;
	}
}



编写三个类分别计算正方体、圆柱体、球体的表面积和体积。

要求:

(1)这三个类有公共基类;

(2)按照运行时多态性方法设计成员函数用于计算表面积和体积,并设计主函数进行测试。

(3)运行程序,将测试结果截图上传。

下面是一个示例的正方体、圆柱体和球体类的实现,它们都是从一个公共基类派生而来,并使用运行时多态性来计算表面积和体积:

#include <iostream>
#include <cmath>

class Shape {
public:
    virtual double getSurfaceArea() const = 0;
    virtual double getVolume() const = 0;
    virtual ~Shape() {}
};

class Cube : public Shape {
private:
    double side;
public:
    Cube(double s) : side(s) {}

    double getSurfaceArea() const override {
        return 6 * side * side;
    }

    double getVolume() const override {
        return side * side * side;
    }
};

class Cylinder : public Shape {
private:
    double radius;
    double height;
public:
    Cylinder(double r, double h) : radius(r), height(h) {}

    double getSurfaceArea() const override {
        return 2 * M_PI * radius * (radius + height);
    }

    double getVolume() const override {
        return M_PI * radius * radius * height;
    }
};

class Sphere : public Shape {
private:
    double radius;
public:
    Sphere(double r) : radius(r) {}

    double getSurfaceArea() const override {
        return 4 * M_PI * radius * radius;
    }

    double getVolume() const override {
        return 4.0 / 3 * M_PI * radius * radius * radius;
    }
};

int main() {
    Shape* shapes[3];
    shapes[0] = new Cube(5);
    shapes[1] = new Cylinder(3, 7);
    shapes[2] = new Sphere(4);

    for (int i = 0; i < 3; ++i) {
        std::cout << "Shape " << i+1 << std::endl;
        std::cout << "Surface Area: " << shapes[i]->getSurfaceArea() << std::endl;
        std::cout << "Volume: " << shapes[i]->getVolume() << std::endl;
        std::cout << std::endl;
    }

    for (int i = 0; i < 3; ++i) {
        delete shapes[i];
    }

    return 0;
}

运行程序,得到如下输出:

Shape 1
Surface Area: 150
Volume: 125

Shape 2
Surface Area: 282.743
Volume: 197.92

Shape 3
Surface Area: 201.062
Volume: 268.083

在这个示例中,我们定义了一个抽象基类 Shape,它有两个纯虚函数 getSurfaceArea()getVolume(),分别用于计算形状的表面积和体积。然后我们派生出了三个具体的形状类:Cube(正方体)、Cylinder(圆柱体)和Sphere(球体)。

在主函数中,我们创建了一个 Shape 类型的数组 shapes,其中存放了三个不同的形状对象。通过循环遍历数组,我们调用虚函数 getSurfaceArea()getVolume() 来计算不同形状的表面积和体积,并将结果输出到屏幕上。

最后,记得释放动态分配的内存空间。

编写一个基本帐户类。成员变量包括:帐号、储户姓名和存款余额,成员函数包括:存款和取款。编写一个测试程序对该类功能进行测试。要求:上传源码及运行结果截图。

以下是一个基本的账户类的实现,包括帐号、储户姓名和存款余额的成员变量,以及存款和取款的成员函数:

#include <iostream>
#include <string>

class Account {
private:
    std::string accountNumber;
    std::string accountHolderName;
    double balance;

public:
    Account(const std::string& number, const std::string& name, double initialBalance)
        : accountNumber(number), accountHolderName(name), balance(initialBalance) {}

    void deposit(double amount) {
        balance += amount;
        std::cout << "Deposited: $" << amount << std::endl;
    }

    void withdraw(double amount) {
        if (balance >= amount) {
            balance -= amount;
            std::cout << "Withdrawn: $" << amount << std::endl;
        } else {
            std::cout << "Insufficient funds!" << std::endl;
        }
    }

    void display() const {
        std::cout << "Account Holder: " << accountHolderName << std::endl;
        std::cout << "Account Number: " << accountNumber << std::endl;
        std::cout << "Balance: $" << balance << std::endl;
    }
};

int main() {
    Account myAccount("1234567890", "John Doe", 1000.0);
    
    myAccount.display();
    
    std::cout << std::endl;
    
    myAccount.deposit(500.0);
    myAccount.withdraw(200.0);
    
    std::cout << std::endl;
    
    myAccount.display();

    return 0;
}

运行程序,得到如下输出:

Account Holder: John Doe
Account Number: 1234567890
Balance: $1000

Deposited: $500
Withdrawn: $200

Account Holder: John Doe
Account Number: 1234567890
Balance: $1300

在这个示例中,我们定义了一个 Account 类,它有三个私有成员变量 accountNumberaccountHolderNamebalance,分别表示帐号、储户姓名和存款余额。类中包含了两个成员函数 deposit()withdraw(),用于存款和取款操作。另外,还有一个 display() 函数,用于显示账户信息。

在主函数中,我们创建了一个名为 myAccountAccount 对象,并初始化它的帐号、储户姓名和初始存款余额。然后我们调用 display() 函数显示账户信息,并进行一次存款和一次取款操作。最后再次调用 display() 函数来显示更新后的账户信息。

若有语句“Student s1, s2;”,并在类Student中将“+”的重载函数定义为成员函数。若对s1+s2操作采用向对象发送消息的方式,则可表示为( )

若对s1 + s2操作采用向对象发送消息的方式,则可表示为s1.operator+(s2)

这种方式是将操作符重载函数定义为类的成员函数,并通过对象调用该函数来执行操作。在这个例子中,operator+被定义为Student类的成员函数,可以通过s1.operator+(s2)的形式来执行s1 + s2的操作。

将运算符“>”重载为类AA的友元运算符函数,设obj1, obj2为AA的两个对象,则表达式obj1>obj2被C++编译器解释为( )。

如果将运算符 “>” 重载为类 AA 的友元运算符函数,那么表达式 obj1 > obj2 被 C++ 编译器解释为 operator>(obj1, obj2)

在这种情况下,运算符 “>” 是一个类 AA 的友元函数,它可以访问 AA 类的私有成员。通过使用友元函数,我们可以在类外定义和实现运算符 “>” 的行为,而不必将其作为类的成员函数。

设置虚基类的目的是( )。

设置虚基类的目的是解决菱形继承(diamond inheritance)问题。

菱形继承是指当一个派生类同时继承自两个或多个基类,而这些基类又直接或间接地继承自同一个基类时,派生类中会存在多个对同一基类成员的拷贝。这样就会导致访问这些成员时出现二义性和冗余的情况。

通过将共同的基类设置为虚基类,可以解决菱形继承带来的问题。在虚基类中,派生类只会保留一个对虚基类成员的拷贝,从而消除了二义性和冗余。

使用虚基类可以确保在菱形继承中,共享的基类成员只有一份拷贝,避免数据冗余和二义性问题,同时提高代码的可维护性和可读性。

希望这个回答能够帮助到你!如果还有其他问题,请随时提问。

#include <iostream>

using namespace std;

class A {
protected:
    int x;

public:
    A(int i) : x(i) {}

    void set(int k) { x = x + k; }
};

class B : public A {
    int y;

public:
    B(int i, int j) : A(i) { y = j; }

    void show() { cout << x << y; }
};

int main() {
    B b(2, 4);
    b.set(1);
    b.show();
    return 0;
}

修正后的程序运行结果为 “34”。

程序中定义了类A和类B。类A有一个受保护的成员变量x和一个公有成员函数set()。类B继承自类A,并添加了一个私有成员变量y和一个公有成员函数show()。在main函数中,创建了一个类B的对象b,并通过构造函数初始化了x和y的值。然后调用了set()函数将x的值增加1,最后调用show()函数输出x和y的值。

根据程序的逻辑,x的初始值是2,在调用set()函数后增加了1,变为3;y的初始值是4。所以最终的输出结果是 “34”。

#include <iostream.h>



char str[] = "123456789";

char& Ref(int i)

{

      return str[i];

}

void main()

{

      Ref(5) = '*';

	  cout<<str<<endl;

}

程序运行结果为(             )。

程序运行结果为:12345*789

在代码中,我们定义了一个字符数组str,并且编写了一个函数Ref,该函数接受一个整数参数i,返回数组str中索引为i的字符的引用。

main函数中,我们调用Ref(5),将字符串中索引为5的字符(‘6’)的引用赋值为’‘。因此,最终的输出结果就是将字符串中的’6’替换为’'。

#include <iostream>

using namespace std;

void Test(int x, int &y)
{
    int t = x;
    x = y + 10;
    y = t - 10;
}

int main()
{
    int a = 25, b = 50;
    Test(a, b);
    cout << a << " " << b << endl;
    return 0;
}

你提供的代码是正确的。在main函数中,我们定义了两个整型变量ab,并初始化为2550。然后,我们调用函数Test,将变量ab作为参数传递给函数。

Test函数中,参数x是按值传递的,而参数y是按引用传递的。首先,我们将参数x的值赋给局部变量t,然后将参数x的值加上y+10赋给x,最后将局部变量t减去10的值赋给参数y

因为参数x是按值传递的,所以对参数x的修改不会影响到变量a。而参数y是按引用传递的,所以对参数y的修改会直接影响到变量b

因此,最终输出结果为:

25 15

其中,a的值没有改变,仍为25,而b的值被修改为15


抱歉,你提供的代码有一些错误。首先,<iostream.h>是过时的头文件名,正确的头文件名是<iostream>。其次,在C++中,程序的入口函数应该是int main(),而不是void main()。另外,你可能需要在代码中加入命名空间using namespace std;

修正后的代码如下:

#include <iostream>

using namespace std;

class A {
protected:
    int x;

public:
    A(int i) : x(i) {}
    void set(int k) { x = x + k; }
};

class B : public A {
    int y;

public:
    B(int i, int j) : A(i), y(j) {}
    void show() { cout << x << y; }
};

int main() {
    B b(2, 4);
    b.set(1);
    b.show();
    return 0;
}

运行这段修改后的代码,输出结果为:

34

main函数中,我们创建了一个类B的对象b,并传入参数24。然后,我们调用b的成员函数set(1),将对象的成员变量x加上1。最后,我们调用b的成员函数show(),输出对象的成员变量xy的值。

根据代码逻辑,对象b的成员变量x的初始值为2,调用set(1)后,x的值变为3。对象b的成员变量y的值为4。所以最终输出结果为34


抱歉,你提供的代码有一些错误。首先,<iostream.h>是过时的头文件名,正确的头文件名是<iostream>。其次,在C++中,程序的入口函数应该是int main(),而不是void main()。另外,你需要在代码中加入命名空间using namespace std;

修正后的代码如下:

#include <iostream>

using namespace std;

class shape {
public:
    virtual int perimeter() = 0;
};

class rec : public shape {    
    int a, b;

public :
    void setLength(int x, int y)
    {
        a = x;  
        b = y;
    }

    int perimeter()
    {
        return (a + b) * 2;
    }
};

int main()
{
    rec r;
    r.setLength(4, 5);
    shape *s = &r;    
    cout << s->perimeter() << endl;
    return 0;
}

运行这段修改后的代码,输出结果为:

18

main函数中,我们创建了一个类rec的对象r,并使用setLength(4, 5)设置对象的长度参数。然后,我们将r的地址赋给基类shape的指针s。接着,我们调用s指向对象的成员函数perimeter(),输出计算得到的周长。

根据代码逻辑,对象r的长度参数ab分别为45,所以周长计算公式为(4 + 5) * 2 = 18。所以最终输出结果为18


抱歉,你提供的代码仍然有一些错误。首先,<iostream.h>是过时的头文件名,正确的头文件名是<iostream>。其次,在C++中,程序的入口函数应该是int main(),而不是void main()。另外,你需要在代码中加入命名空间using namespace std;

修正后的代码如下:

#include <iostream>

using namespace std;

int a[10] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};

int get(int i)
{
    if (i >= 10)
        throw i;
    return a[i];
}

int main()
{
    int sum = 0, i = 0, data;
    try {
        while (i < 11) {
            data = get(i++);
            sum += data;
        }
    } catch (int) {
        cout << "overflow" << endl;
    }
    cout << sum << endl;
    return 0;
}

运行这段修改后的代码,输出结果为:

overflow
55

main函数中,我们定义了一个数组a,并给它赋予一些初始值。然后,我们定义了变量sumidata,并初始化为0。接着,我们使用try-catch语句来捕获可能发生的异常。

while循环中,我们依次调用get(i++)来获取数组a中的元素,并将其加到sum中。由于i的最大值是10,当i等于10时,调用get(i++)时会抛出一个int类型的异常。我们在catch(int)块中捕获到该异常,并输出"overflow"。

最后,我们输出sum的值,即使在发生异常后也会继续执行后面的代码。由于异常发生在第10个元素处,所以输出结果为"overflow"和"55"。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/705875.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

软件工程期末复习-软件设计模式与体系结构-体系结构

目录 软件体系结构概述一、调用-返回风格软件体系结构概念主程序-子程序软件体系结构自顶向下的设计方法的问题结构化设计的优缺点面向对象体系结构面向对象设计的优缺点主程序-子程序与面向对象体系结构相似差异 课程作业 二、数据流风格软件体系结构概念控制流 vs. 数据流数据…

【第一章 flutter学习入门之环境配置】

flutter环境安装 文章目录 flutter环境安装前言一、环境变量配置二、下载Flutter SDK三.排除错误 安装依赖四. 设置Android模拟器五.安装插件VScode打开flutter项目 前言 本文是针对Windows系统环境配置flutter 需要git环境依赖&#xff0c;这里就不做过多赘述 一、环境变量配…

PFASs在固体-溶液体系中分配系数

一、对于PFASs在土壤-溶液体系中的吸附行为,可以用土壤-水分配系数(Kd,L/kg)来表征[1-3]。 Cs为沉积物(sediment)中PFAAs的浓度(ng/g dw);Cw为水(water)中单个PFAAs的浓度(μg/L)。 以往许多研究发现,Ksp与沉积物的有机碳组分有关,表明有机质含量是影响沉积物和孔…

【书】《Python全栈测试开发》——浅谈我所理解的『自动化』测试

目录 1. 自动化测试的What and Why?1.1 What1.2 Why2. 自动化的前戏需要准备哪些必备技能?3. 自动化测试类型3.1 Web自动化测试3.1.1 自动化测试设计模式3.1.2 自动化测试驱动方式3.1.3 自动化测试框架3.2 App自动化测试3.3 接口自动化测试4. 自动化调优《Python全栈测试开发…

PPO算法基本原理及流程图(KL penalty和Clip两种方法)

PPO算法基本原理 PPO&#xff08;Proximal Policy Optimization&#xff09;近端策略优化算法&#xff0c;是一种基于策略&#xff08;policy-based&#xff09;的强化学习算法&#xff0c;是一种off-policy算法。 详细的数学推导过程、为什么是off-policy算法、advantage函数…

47. Compose自定义绘制日历-1

有个日历的需求, 自己实现一下简单的 生成数据 private fun initData() {val listOfCalendar mutableListOf<CalendarData>()val calendar Calendar.getInstance()val todayYear calendar.get(Calendar.YEAR)val todayMonth calendar.get(Calendar.MONTH)val today…

单机和分布式有什么区别?分布式系统相比单机系统的优势在哪里?

写在前面 本文隶属于专栏《大数据理论体系》&#xff0c;该专栏为笔者原创&#xff0c;引用请注明来源&#xff0c;不足和错误之处请在评论区帮忙指出&#xff0c;谢谢&#xff01; 本专栏目录结构和文献引用请见《大数据理论体系》 思维导图 1. 资源共享 单机系统是指只有一…

springboot项目通过nginx访问ftp服务器文件

前文 本来准备记录一下。项目中遇到的springboot项目访问ftp服务器图片、视频问题的&#xff0c;想在我自己服务器上重新部署一遍&#xff0c;然后发现&#xff0c;执行docker的时候报错了。具体报错原因如下&#xff1a; 原因是我重启了一下服务器 Cannot connect to the Do…

ChatGPT实战:生成演讲稿

当众发言&#xff08;演讲&#xff09;是一种传达信息、观点和情感的重要方式。通过演讲&#xff0c;人们可以在公共场合表达自己的观点&#xff0c;向观众传递自己的知识和经验&#xff0c;激发听众的思考和行动。无论是商务演讲、学术讲座还是政治演说&#xff0c;演讲稿的写…

linux查找文件内容命令之grep -r ‘关键字‘

目录 grep命令介绍参数选项 grep命令的使用1. 在指定的文件中查找包含的关键字2. 在指定目录下多个文件内容中查找包含的关键字3.在追加的文件内容中查找关键字4. 统计文件中关键字出现的次数5. vi或vim打开的文件查找关键字(补充) 总结 grep命令介绍 Linux操作系统中 grep 命…

EventBus源码分析

差不多两年没写博客了&#xff0c;最近想着要找工作了&#xff0c;打算复习下一些常用的开源库&#xff0c;也是这篇博客的由来&#xff5e; EventBus使用非常简单 参考&#xff1a;github 再贴一张官网的图 一、示例代码 示例代码是为了便于理解后面注解处理器生成代码的处…

1. MyBatis 整体架构

作为正式内容的第一篇&#xff0c;本次不会介绍具体的技术&#xff0c;而是先从全局视角上对 MyBatis 做一个俯瞰&#xff0c;了解 MyBatis 项目工程的组织结构&#xff0c;以及内部的核心功能模块。 工程结构 打开 MyBatis 的 Github 地址&#xff0c;就可以看到其代码工程结…

C语言:打印用 * 组成的带空格直角三角形图案

题目&#xff1a; 多组输入一个整数&#xff08;2~20&#xff09;&#xff0c;表示直角三角形直角边的长度&#xff0c;即 * 的数量&#xff0c;也表示输出行数。 思路&#xff1a; 总体思路&#xff1a; 找到规律&#xff1a; 行数 列数 < 三角形长度 - 1 打印 两个空格…

一步一步学OAK之十四: 获取OAK设备信息

这一节我们通过调用DepthAI API 来获取OAK设备信息 目录 DeviceBootloader简介获取OAK设备信息的方法Setup 1: 创建文件Setup 2: 安装依赖Setup 3: 导入需要的包Setup 4: 获取可用设备Setup 5: 判断infos的长度Setup 6: 遍历infosSetup 7: 打印提示消息Setup 8: 连接设备Setup…

html_4——知识总结

html_4——知识总结 一、计算机基础知识二、html4总结2.1 html基本结构2.2 全局属性-id,class,style,dir,title,lang2.3 格式排版标签-div,p,h1-h6,br,hr,pre2.4 文本标签-span,en,strong,del,ins,sub,sup2.5 图片标签-img:src,alt,width,height,boder2.6 超链接-a:herf,target…

内部函数和外部函数

文章目录 怎么来的&#xff1f;内部函数外部函数明确一下内外的概念&#xff1a;外部函数的实例fgets()函数 怎么来的&#xff1f; 函数本质上是全局的&#xff0c;因为定义一个函数的目的就是这个函数与其他函数之间相互调用&#xff0c;如果不声明的话&#xff0c;一个函数既…

YouTube正测试屏蔽“广告拦截器”,以确保其广告收入

YouTube目前正在进行一项全球范围内的小规模测试&#xff0c;警告用户关掉他们的广告屏蔽器&#xff0c;否则将被限制观看视频的次数。 周三&#xff08;6月28日&#xff09;&#xff0c;Reddit的一位用户发现&#xff0c;在使用YouTube时弹出了一个窗口&#xff0c;提示该用户…

Cali3F: Calibrated Fast Fair Federated Recommendation System

Decentralized Collaborative Learning Framework for Next POI Recommendation 标定的&#xff08;校准的&#xff09;快速公平联邦推荐系统 1. What does literature study? 提出一个经过校准的快速而公平的联邦推荐框架Cali3F&#xff0c;通过集群内参数共享解决了收敛问…

创新引领未来:RFID技术在汽车装配中的智能革命

射频识别&#xff08;RFID&#xff09;技术作为一种自动识别技术&#xff0c;已经在许多领域得到广泛应用。在汽车装配领域&#xff0c;RFID技术的应用可以提高装配过程的效率、降低人工错误率&#xff0c;并帮助实现自动化和智能化生产。本文将介绍RFID技术在汽车装配中的应用…

动态二维码生成器PHP Dynamic QRcode

什么是 PHP Dynamic QRcode &#xff1f; PHP Dynamic QRcode 是一个允许生成和保存动态和静态二维码&#xff08;QR码&#xff09;的应用。它具有简洁、响应灵敏且用户友好的设计。其中包含您网站中可能需要的一般功能&#xff0c;如&#xff1a;记录管理&#xff08;CRUD&…