基于《C++ Primer Plus》,进行了系统的构建。
vect.h
//
// Created by JAN on 2022/1/18.
//
#ifndef C___VECT_H
#define C___VECT_H
#include <iostream>
namespace VECTOR
{
void menu();
class Vector
{
public:
enum Mode {RECT, POL};
private:
double x;
double y;
double mag;
double ang;
Mode mode;
void set_mag();
void set_ang();
void set_x();
void set_y();
public:
Vector();
Vector(double n1, double n2, Mode form = RECT);
void rest(double n1, double n2, Mode form = RECT);
~Vector();
double xval() const { return x; }
double yval() const { return y; }
double magval() const { return mag; }
double angval() const { return ang; }
void polar_mode();
void rect_mode();
Vector operator+(const Vector &b) const;
Vector operator-(const Vector &b) const;
Vector operator-() const;
Vector operator*(double n) const;
friend Vector operator*(double n, const Vector &a);
friend std::ostream& operator<<(std::ostream &os, const Vector &v);
friend std::istream& operator>>(std::istream &is, Vector &v);
};
}
#endif //C___VECT_H
vect.cpp
//
// Created by JAN on 2022/1/18.
//
#include <cmath>
#include "vect.h"
using std::sqrt;
using std::sin;
using std::cos;
using std::atan;
using std::atan2;
using std::cout;
using std::cin;
namespace VECTOR
{
void menu()
{
cout << "0.退出程序\n";
cout << "1.对向量进行输入\n";
cout << "2.查看向量\n";
cout << "3.改变向量模式\n";
cout << "4.进行向量运算\n";
}
const double Rad_to_deg = 45.0 / atan(1.0);
void Vector::set_mag()
{
mag = sqrt(x * x + y * y);
}
void Vector::set_ang()
{
if(x == 0 && y == 0){
ang = 0;
}else{
ang = atan2(y,x);
}
}
void Vector::set_x()
{
x = mag * cos(ang);
}
void Vector::set_y()
{
y = mag * sin(ang);
}
Vector::Vector()
{
mag = ang = x = y = 0;
mode = RECT;
}
Vector::Vector(double n1, double n2, Mode form)
{
mode = form;
if(form == RECT){
x = n1;
y = n2;
set_mag();
set_ang();
}else if(mode == POL){
mag = n1;
ang = n2;
set_x();
set_y();
}else{
cout << "Incorrect 3rd argument to Vector() -- ";
cout << "vector set to 0\n";
x = y = mag = ang = 0;
mode = RECT;
}
}
void Vector::rest(double n1, double n2, Mode form)
{
mode = form;
if(form == RECT){
x = n1;
y = n2;
set_mag();
set_ang();
}else if(mode == POL){
mag = n1;
ang = n2;
set_x();
set_y();
}else{
cout << "Incorrect 3rd argument to Vector() -- ";
cout << "vector set to 0\n";
x = y = mag = ang = 0;
mode = RECT;
}
}
Vector::~Vector() = default;
void Vector::polar_mode()
{
mode = POL;
}
void Vector::rect_mode()
{
mode = RECT;
}
Vector Vector::operator+(const Vector &b) const
{
return Vector{x + b.x, y + b.y};
}
Vector Vector::operator-(const Vector &b) const
{
return Vector{x - b.x, y - b.y};
}
Vector Vector::operator-() const
{
return Vector{-x, -y};
}
Vector Vector::operator*(double n) const
{
return Vector{x * n, y * n};
}
//friend
Vector operator*(double n, const Vector &a)
{
return a * n;
}
std::ostream& operator<<(std::ostream &os, const Vector &v)
{
if(v.mode == Vector::RECT){
os << "(x,y) = (" << v.x <<"," << v.y << ")";
}else if(v.mode == Vector::POL){
os << "(m,a) = (" << v.mag << "," << v.ang * Rad_to_deg <<")";
}else{
os << "Vector object mode is invalid";
}
return os;
}
std::istream& operator>>(std::istream &is, Vector &v)
{
double a,b;
cin >> a >> b;
if(v.mode == Vector::RECT){
v.rest(a,b,Vector::RECT);
}else if(v.mode == Vector::POL){
v.rest(a,b,Vector::POL);
}else{
std::cout << "Vector object mode is invalid";
}
return is;
}
}
main.cpp
#include "vect.h"
using namespace VECTOR;
using std::string;
using std::cin;
using std::cout;
int main()
{
const string rect = "rect";
const string pol = "pol";
int choose;
Vector vec;
string mode;
int a,b;
while(true)
{
menu();
cout << "Which function: ";
cin >> choose;
if(!choose) break;
switch (choose) {
case 1:
{
cout << "Which mode :";
cin >> mode;
if(mode == rect){
cout << "Please enter x and y: ";
cin >> a >> b;
vec.rest(a,b,Vector::RECT);
}else if(mode == pol){
cout << "Please entre mag ang ang: ";
cin >> a >> b;
vec.rest(a,b,Vector::POL);
}else{
cout << "input error\n";
}
break;
}
case 2:
{
cout << "Which model of ves do you want to see: ";
cin >> mode;
if(mode == rect){
cout << "use class function\n";
cout << vec.xval();
cout << std::endl;
cout << vec.yval();
cout <<"\nuse << ";
cout << Vector{vec.xval(),vec.yval(),Vector::RECT} << std::endl;
}else if(mode == pol){
cout << "use class function\n";
cout << vec.magval();
cout << std::endl;
cout << vec.angval();
cout <<"\nuse << ";
cout << Vector{vec.magval(),vec.angval(),Vector::POL} << std::endl;
}else{
cout << "input error\n";
}
break;
}
case 3:
{
cout << "Which mode: ";
cin >> mode;
if(mode == rect){
vec.rect_mode();
}else if(mode == pol){
vec.polar_mode();
}else{
cout << "input error\n";
}
break;
}
case 4:
{
Vector v1,v2;
char op;
cout << "Which mode: ";
cin >> mode;
if(mode == pol){
v1.polar_mode();
v2.polar_mode();
}else if(mode != rect){
cout << "input error\n";
break;
}
cout << "Which op: ";
cin >> op;
if(op == '+'){
cin >> v1 >> v2;
cout << v1 + v2 << std::endl;
}else if(op == '-'){
cin >> v1 >> v2;
cout << v1 - v2 << std::endl;
}else if(op == '*'){
double n;
cin >> n;
cin >> v1;
cout << n << "*" << "vector =";
cout << n * v1 << std::endl;
}
break;
}
default :
break;
}
}
return 0;
}
总结
我们看到《C++ Primer Plus》中设计的vector类,其OPP编程思想无处不见
1.做好数据的隐藏,这里在主函数中的switch完全可以封装成一个函数,放在namespace VECTOR里
2.头文件尽量简洁,变量名函数名尽可能可做到见名知意,对于短小的类方法,可以写在头文件中,变成内联函数,可以提升程序效率
3.对于一个类,也尽量做到高聚合,低耦合,类方法间尽量不要冲突,拆成细小的function,进行不断组装。
4.函数要尽量短小精悍,不易过长,不同函数功能间的功能尽可能不要冲突。
5.关于代码风格,头文件中一类型的写在一起,中间用换行隔开,让代码看起来整齐,美观。