利用多态机制完成以下题目
现需要一个理财程序,其中包含四个类,分别为投资(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); // 创建一个理财人对象,初始本金为 100000Wang.addInvest(new Saving(50000)); // 添加一个储蓄投资,投资金额为 50000Wang.addInvest(new Fund(20000)); // 添加一个基金投资,投资金额为 20000std::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;
}