利用多态机制完成以下题目
现需要一个理财程序,其中包含四个类,分别为投资(Investment)、储蓄(Saving)、基金(Fund)和理财人(Person),储蓄和基金为两种具体投资,都有确定的投资金额(m_capital),但它们年底结算(setrle)的方式不同。储蓄的结算方式如下:
m_capital = m_capital * (1+1.78/100);
基金的结算方式如下:
m_capital =m_capital * (rand()%20 +90)/100;
理财人实例化时确定本金m_cashFlow。理财人通过其成员函数addInvest 添加具体投资,将新建的投资类实例的地址保存在vector 类型的成员mv_invests中,并从本金中减去投资额。一年后,理财人通过其成员函数settle结算所有投资,将投资额返回本金。实现效果如下:
//初始本金十万元
Person Wang(100000);
//储蓄、基金分别投资五万、两万
Wang.addInvest(Saving(50000));
Wang.addInvest (Fund(20000));
//年底全部结算转入本金
cout<<Wang.settle()<<endl;
请据此给出投资、储蓄、基金、理财人这四个类的定义,并利用上述代码进行测试。
#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>
// 投资基类
class Investment {
public:
// 构造函数,初始化投资金额
Investment(double capital) : m_capital(capital) {}
// 获取投资金额的方法,声明为 const,不改变对象状态
double getCapital() const {
return m_capital;
}
// 纯虚函数,用于派生类实现投资结算逻辑
virtual double settle() = 0;
protected:
double m_capital; // 投资金额
};
// 储蓄类,继承自投资基类
class Saving : public Investment {
public:
// 构造函数,调用基类构造函数初始化投资金额
Saving(double capital) : Investment(capital) {}
// 实现投资结算逻辑
double settle() override {
m_capital *= (1 + 1.78 / 100); // 年底结算方式:本金增加 1.78%
return m_capital; // 返回年底结算后的本金
}
};
// 基金类,继承自投资基类
class Fund : public Investment {
public:
// 构造函数,调用基类构造函数初始化投资金额
Fund(double capital) : Investment(capital) {}
// 实现投资结算逻辑
double settle() override {
m_capital *= (rand() % 20 + 90) / 100.0; // 年底结算方式:本金按 90%~109% 之间的随机比例变动
return m_capital; // 返回年底结算后的本金
}
};
// 理财人类
class Person {
public:
// 构造函数,初始化理财人本金
Person(double cashFlow) : m_cashFlow(cashFlow) {}
// 添加投资,将投资金额从本金中扣除,并保存投资对象的指针
void addInvest(Investment* invest) {
m_cashFlow -= invest->getCapital(); // 本金减去投资金额
mv_invests.push_back(invest); // 将投资对象指针保存到投资对象容器中
}
// 年底结算,对所有投资进行结算,并将结算后的金额返回到本金中
double settle() {
double totalCapital = 0; // 总投资金额
// 遍历所有投资对象,进行结算
for (auto& invest : mv_invests) {
totalCapital += invest->settle(); // 累加所有投资的结算金额
}
m_cashFlow += totalCapital; // 将结算后的金额追加到本金中
return m_cashFlow; // 返回年底结算后的本金
}
// 公有接口,用于获取投资对象容器
const std::vector<Investment*>& getInvests() const {
return mv_invests; // 返回投资对象容器
}
private:
double m_cashFlow; // 理财人的本金
std::vector<Investment*> mv_invests; // 投资对象容器
};
int main() {
srand(time(nullptr)); // 初始化随机数种子
Person Wang(100000); // 创建一个理财人对象,初始本金为 100000
Wang.addInvest(new Saving(50000)); // 添加一个储蓄投资,投资金额为 50000
Wang.addInvest(new Fund(20000)); // 添加一个基金投资,投资金额为 20000
std::cout << "年底结算后的本金:" << Wang.settle() << std::endl; // 输出年底结算后的本金
// 释放动态分配的内存
for (auto& invest : Wang.getInvests()) {
delete invest;
}
return 0;
}
已知Point类和LineString折线类定义如下,请写出LineString类的各个成员函数的实现。
class Point { public:double x, y; };
class LineString {//由多个点组成的线串类,由n个点组成的折线包含n-1个线段
public:
LineString(Point* pnts, int num); //构造函数,通过传入点数组来构造
LineString(const LineString& another); //复制构造函数
~LineString();//析构函数
LineString& operator=(const LineString& rhs);//赋值函数
Point& operator[](int index);//返回线串中第index个点的引用
private:
Point* m_data;//用于保存组成线串的点
int m_num;// 线串中点的数量
};
#include <iostream>
#include <cassert> // 引入 assert 头文件以使用断言
using namespace std;
// 定义点类
class Point {
public:
double x, y;
// 默认构造函数
Point() : x(0), y(0) {}
// 带参构造函数
Point(double _x, double _y) : x(_x), y(_y) {}
};
// 定义线串类
class LineString {
public:
// 默认构造函数
LineString() : m_data(nullptr), m_num(0) {}
// 构造函数,通过传入点数组来构造线串
LineString(Point* pnts, int num) {
m_num = num; // 设置线串中点的数量
m_data = new Point[num]; // 分配动态内存用于存储点数组
for (int i = 0; i < num; ++i) {
m_data[i] = pnts[i]; // 复制传入的点数组到线串的内部存储中
}
}
// 复制构造函数,用于创建新线串对象时复制另一个线串对象的内容
LineString(const LineString& another) {
m_num = another.m_num; // 复制另一个线串对象中的点数量
m_data = new Point[m_num]; // 分配动态内存用于存储新线串对象的点数组
for (int i = 0; i < m_num; ++i) {
m_data[i] = another.m_data[i]; // 复制另一个线串对象的点数组到新线串对象的内部存储中
}
}
// 析构函数,用于释放线串对象的动态内存
~LineString() {
delete[] m_data;
}
// 赋值函数,用于将一个线串对象赋值给另一个线串对象
LineString& operator=(const LineString& rhs) {
if (this == &rhs) return *this; // 检查自赋值情况
delete[] m_data; // 释放原有的动态内存
m_num = rhs.m_num; // 复制另一个线串对象的点数量
m_data = new Point[m_num]; // 分配动态内存用于存储新线串对象的点数组
for (int i = 0; i < m_num; ++i) {
m_data[i] = rhs.m_data[i]; // 复制另一个线串对象的点数组到新线串对象的内部存储中
}
return *this;
}
// 重载下标运算符,用于访问线串对象中的点数组中的某个点
Point& operator[](int index) {
assert(index >= 0 && index < m_num); // 使用断言确保索引合法
return m_data[index];
}
private:
Point* m_data; // 用于保存线串对象中的点数组
int m_num; // 线串中点的数量
};
int main() {
// 创建一些点对象
Point p1(1.0, 1.0);
Point p2(2.0, 2.0);
Point p3(3.0, 3.0);
// 创建一个点数组
Point pnts[] = { p1, p2, p3 };
// 使用点数组构造一个线串对象
LineString ls(pnts, 3);
// 测试复制构造函数,将已有的线串对象复制给新线串对象
LineString ls_copy = ls;
// 测试赋值函数,将已有的线串对象赋值给另一个线串对象
LineString ls_assigned;
ls_assigned = ls;
// 输出线串对象中各个点的坐标
for (int i = 0; i < 3; ++i) {
cout << "Point " << i + 1 << ": (" << ls[i].x << ", " << ls[i].y << ")" << endl;
}
return 0;
}
已知String类定义如下:
class String
{
public:
String(const char*str=NULL);//通用拷贝函数
String(const String&another);//拷贝构造函数
~String();//析构函数
String &operator=(const String&rhs);//赋值函数
operator const char *();//强制转换
private:
char *m_data;//用于保存字符串
};
请写出String类的各个成员函数的实现
#include <iostream>
#include <cstring>
#pragma warning(disable:4996)
class String
{
public:
String(const char* str = nullptr); // 通用拷贝函数
String(const String& another); // 拷贝构造函数
~String(); // 析构函数
String& operator=(const String& rhs); // 赋值函数
operator const char* (); // 强制转换
private:
char* m_data; // 用于保存字符串
};
String::String(const char* str) {
if (str == nullptr) {
m_data = new char[1];
*m_data = '\0';
}
else {
m_data = new char[strlen(str) + 1];
strcpy(m_data, str);
}
}
String::String(const String& another) {
m_data = new char[strlen(another.m_data) + 1];
strcpy(m_data, another.m_data);
}
String::~String() {
delete[] m_data;
}
String& String::operator=(const String& rhs) {
if (this != &rhs) {
delete[] m_data;
m_data = new char[strlen(rhs.m_data) + 1];
strcpy(m_data, rhs.m_data);
}
return *this;
}
String::operator const char* () {
return m_data;
}
int main() {
// 测试构造函数
String s1("Hello, world!");
String s2(s1); // 使用拷贝构造函数
std::cout << "s1: " << s1 << std::endl;
std::cout << "s2: " << s2 << std::endl;
// 测试赋值函数
String s3;
s3 = s1; // 使用赋值函数
std::cout << "s3: " << s3 << std::endl;
return 0;
}
定义抽象类型Shape ,包含计算图形面积的纯虚函数Area ,由他派生三个类:Circle。Rectangle、Trapezoid 另外重载运算符+ 以支持如下测试代码
Circle c(10);
Rectangle r(4,5);
Trapezoid t(5,6,2);
double area=c+r+t;//计算c r t的面积和
提示:需要两个互为重载的运算符函数,且一个函数的两个参数为Shape的引用,另一个函数的两个参数为double和Shape的引用
#include <iostream>
class Shape {
public:
virtual double Area() const = 0; // 纯虚函数
virtual ~Shape() {} // 虚析构函数,确保正确释放资源
};
class Circle : public Shape {
private:
double radius;
public:
Circle(double r) : radius(r) {}
double Area() const override {
return 3.14 * radius * radius;
}
};
class Rectangle : public Shape {
private:
double width, height;
public:
Rectangle(double w, double h) : width(w), height(h) {}
double Area() const override {
return width * height;
}
};
class Trapezoid : public Shape {
private:
double a, b, h;
public:
Trapezoid(double a1, double b1, double h1) : a(a1), b(b1), h(h1) {}
double Area() const override {
return (a + b) * h / 2;
}
};
// 重载运算符+,两个参数为Shape的引用
double operator+(const Shape& s1, const Shape& s2) {
return s1.Area() + s2.Area();
}
// 重载运算符+,一个参数为double,另一个参数为Shape的引用
double operator+(double d, const Shape& s) {
return d + s.Area();
}
int main() {
Circle c(10);
Rectangle r(4, 5);
Trapezoid t(5, 6, 2);
// 计算c r t的面积和
double area = c + r + t;
std::cout << "Total area: " << area << std::endl;
return 0;
}
设计复数类Complex ,包含double类型的实部和虚部,实现运算符+-*以及输出符号的重载 。Complex的调用如main函数所示。
#include<iostream>
using namespace std;
void main() {
Complex c1(2.0, 3.0);
Complex c2(1.0, 2.0);
cout<<c1+c2<<endl;
cout<<c1-c2<<endl;
cout<<c1*c2<<endl;
}
#include <iostream>
using namespace std;
class Complex {
private:
double real;
double imag;
public:
// 构造函数
Complex(double r = 0.0, double i = 0.0) : real(r), imag(i) {}
// 重载加法运算符+
Complex operator+(const Complex& other) const {
return Complex(real + other.real, imag + other.imag);
}
// 重载减法运算符-
Complex operator-(const Complex& other) const {
return Complex(real - other.real, imag - other.imag);
}
// 重载乘法运算符*
Complex operator*(const Complex& other) const {
double r = real * other.real - imag * other.imag;
double i = real * other.imag + imag * other.real;
return Complex(r, i);
}
// 重载输出运算符<<
friend ostream& operator<<(ostream& out, const Complex& c) {
out << "(" << c.real << ", " << c.imag << "i)";
return out;
}
};
int main() {
Complex c1(2.0, 3.0);
Complex c2(1.0, 2.0);
cout << c1 + c2 << endl; // 输出 c1 + c2 的结果
cout << c1 - c2 << endl; // 输出 c1 - c2 的结果
cout << c1 * c2 << endl; // 输出 c1 * c2 的结果
return 0;
}