先看源代码:
//main.cpp
#include <iostream>
#include "Matrix.h"
using namespace std;
const int str_length = 7;//经测试,至少为7;印证了每个汉字占2个字节('\0'占一个字节)
int main() {
int size;
char style[str_length];
char key_point[str_length];
cout << "请输入矩阵的边长 N: ";
cin >> size;
cout << "请输入填充方式(顺时针、逆时针、行优先、列优先): ";
cin >> style;
cout << "请输入从哪一个角开始填充(左上角、左下角、右上角、右下角): ";
cin >> key_point;
Style obj(size);
obj.fill_style(style, key_point);
obj.findPosition();
obj.fill();
cout << obj;
return 0;
}
//Matrix.h
#ifndef Matrix_h
#define Matrix_h
#include <iostream>
using namespace std;
class Matrix{
public:
int _size;//方阵的规模
int *_data;//数据空间
int row, col;
char dir;//用于顺时针、逆时针、行优先、列优先时的方向判定
char* _style;//填充方式(顺时针、逆时针、行优先、列优先)
char* _key_point;//填充关键点,根据情况赋值为四个角
Matrix(int size);
~Matrix();
void fill();
virtual int findPosition() = 0;//关键一笔!用纯虚函数定义接口
friend ostream& operator<< (ostream& out, const Matrix& m);
};
class ClockwiseMatrix:public Matrix{
public:
using Matrix::Matrix;
int findPosition();//顺时针辅助函数
};
class AnticlockMatrix:public Matrix{
public:
using Matrix::Matrix;
int findPosition();//逆时针辅助函数
};
class RowFirstMatrix:public Matrix{
public:
using Matrix::Matrix;
int findPosition();//行优先辅助函数
};
class ColFirstMatrix:public Matrix{
public:
using Matrix::Matrix;
int findPosition();//列优先辅助函数
};
class Style:public Matrix{
//Style不能继承Matrix,否则Style不能实例化对象,因为继承后Style也是抽象类
//除非在Style中定义了继承来的Matrix中的纯虚函数,这样Style就不是抽象类了,
//就可以实例化对象。同时测试表明:纯虚函数不能用= delete删除。
public:
using Matrix::Matrix;
void fill_style(char* str1, char* str2);
int findPosition();//定义纯虚函数,让Style不是抽象类
ClockwiseMatrix Clockwise;//在一个类的成员函数中调用另一个类的成员函数,
AnticlockMatrix Anticlock;//除了继承这一方法以外,第二种方法就是类A中
RowFirstMatrix RowFirst;//定义类B的一个对象,然后在类A的成员函数中就可以
ColFirstMatrix ColFirst;//通过对象名加点运算符的方式调用类B的成员函数了。
};
#endif
//Matrix.cpp
#include <iostream>
#include <cstring>
#include "Matrix.h"
using namespace std;
Matrix::Matrix(int size): _size(size) {
_data = new int[size * size];
memset(_data, 0, sizeof(int) * _size * _size);
}
Matrix::~Matrix(){
delete _data;
}
ostream& operator<< (ostream& out, const Matrix& m){
for(int r = 0; r < m._size; r++){ //row
for(int c = 0; c < m._size; c++) //col
cout << *(m._data + r * m._size + c) << '\t';
cout << endl;
}
}
void Matrix::fill(){
for(int num = 1; num <= _size * _size; num++){
int pos = findPosition();
_data[pos] = num;
}
}
//Style.cpp
#include <iostream>
#include <cstring>
#include "Matrix.h"
using namespace std;
void Style::fill_style(char* str1, char* str2){
_style = str1;
_key_point = str2;
}
int Style::findPosition(){
if(strcmp(_style, "顺时针") == 0){
Clockwise._size = _size;
if(strcmp(_key_point, "左上角") == 0){
Clockwise.row = 0;
Clockwise.col = -1;
Clockwise.dir = 'R';
return Clockwise.findPosition();
}
if(strcmp(_key_point, "右上角") == 0){
Clockwise.row = -1;
Clockwise.col = _size - 1;
Clockwise.dir = 'D';
return Clockwise.findPosition();
}
if(strcmp(_key_point, "右下角") == 0){
Clockwise.row = _size - 1;
Clockwise.col = _size;
Clockwise.dir = 'L';
return Clockwise.findPosition();
}
if(strcmp(_key_point, "左下角") == 0){
Clockwise.row = _size;
Clockwise.col = 0;
Clockwise.dir = 'U';
return Clockwise.findPosition();
}
}
if(strcmp(_style, "逆时针") == 0){
Anticlock._size = _size;
if(strcmp(_key_point, "左上角") == 0){
Anticlock.row = -1;
Anticlock.col = 0;
Anticlock.dir = 'D';
return Anticlock.findPosition();
}
if(strcmp(_key_point, "左下角") == 0){
Anticlock.row = _size - 1;
Anticlock.col = -1;
Anticlock.dir = 'R';
return Anticlock.findPosition();
}
if(strcmp(_key_point, "右下角") == 0){
Anticlock.row = _size;
Anticlock.col = _size - 1;
Anticlock.dir = 'U';
return Anticlock.findPosition();
}
if(strcmp(_key_point, "右上角") == 0){
Anticlock.row = 0;
Anticlock.col = _size;
Anticlock.dir = 'L';
return Anticlock.findPosition();
}
}
if(strcmp(_style, "行优先") == 0){
RowFirst._size = _size;
if(strcmp(_key_point, "左上角") == 0){
RowFirst.row = 0;
RowFirst.col = -1;
RowFirst.dir = 'D';
return RowFirst.findPosition();
}
if(strcmp(_key_point, "右上角") == 0){
RowFirst.row = 0;
RowFirst.col = _size;
RowFirst.dir = 'L';
return RowFirst.findPosition();
}
if(strcmp(_key_point, "左下角") == 0){
RowFirst.row = _size - 1;
RowFirst.col = -1;
RowFirst.dir = 'R';
return RowFirst.findPosition();
}
if(strcmp(_key_point, "右下角") == 0){
RowFirst.row = _size - 1;
RowFirst.col = _size;
RowFirst.dir = 'U';
return RowFirst.findPosition();
}
}
if(strcmp(_style, "列优先") == 0){
ColFirst._size = _size;
if(strcmp(_key_point, "左上角") == 0){
ColFirst.row = -1;
ColFirst.col = 0;
ColFirst.dir = 'D';
return ColFirst.findPosition();
}
if(strcmp(_key_point, "右上角") == 0){
ColFirst.row = -1;
ColFirst.col = _size - 1;
ColFirst.dir = 'L';
return ColFirst.findPosition();
}
if(strcmp(_key_point, "左下角") == 0){
ColFirst.row = _size;
ColFirst.col = 0;
ColFirst.dir = 'R';
return ColFirst.findPosition();
}
if(strcmp(_key_point, "右下角") == 0){
ColFirst.row = _size;
ColFirst.col = _size - 1;
ColFirst.dir = 'U';
return ColFirst.findPosition();
}
}
}
//ClockwiseMatrix.cpp
#include <iostream>
#include "Matrix.h"
using namespace std;
int ClockwiseMatrix::findPosition(){
switch(dir){
case 'D':
if(row < _size - 1 && _data[(row + 1) * _size + col] == 0)
row++;
else{
dir = 'L'; // next direction
col--;
}
break;
case 'L':
if(col > 0 && _data[row * _size + col - 1] == 0)
col--;
else{
dir = 'U'; // next direction
row--;
}
break;
case 'U':
if(row > 0 && _data[(row - 1) * _size + col] == 0)
row--;
else{
dir = 'R'; // next direction
col++;
}
break;
case 'R':
if(col < _size - 1 && _data[row * _size + col + 1] == 0)
col++;
else{
dir = 'D'; // next direction
row++;
}
break;
}
return row * _size + col;
}
//AnticlockMatrix.cpp
#include <iostream>
#include "Matrix.h"
using namespace std;
int AnticlockMatrix::findPosition(){
switch(dir){
case 'D':
if(row < _size - 1 && _data[(row + 1) * _size + col] == 0)
row++;
else{
dir = 'R'; // next direction
col++;
}
break;
case 'R':
if(col < _size - 1 && _data[row * _size + col + 1] == 0)
col++;
else{
dir = 'U'; // next direction
row--;
}
break;
case 'U':
if(row > 0 && _data[(row - 1) * _size + col] == 0)
row--;
else{
dir = 'L'; // next direction
col--;
}
break;
case 'L':
if(col > 0 && _data[row * _size + col - 1] == 0)
col--;
else{
dir = 'D'; // next direction
row++;
}
break;
}
return row * _size + col;
}
//RowFirstMatrix.cpp
#include <iostream>
#include "Matrix.h"
using namespace std;
int RowFirstMatrix::findPosition(){
switch(dir){
case 'D'://行优先且向右且向下填充(左上角)
if(col < _size - 1 && _data[row * _size + col + 1] == 0)
col++;
else
if(row < _size - 1){
row++;
col = 0;
}
break;
case 'L'://行优先且向左且向下填充(右上角)
if(col > 0 && _data[row * _size + col - 1] == 0)
col--;
else
if(row < _size - 1){
row++;
col = _size - 1;
}
break;
case 'R'://行优先且向右且向上填充(左下角)
if(col < _size - 1 && _data[row * _size + col + 1] == 0)
col++;
else
if(row > 0){
row--;
col = 0;
}
break;
case 'U'://行优先且向左且向上填充(右下角)
if(col > 0 && _data[row * _size + col - 1] == 0)
col--;
else
if(row > 0){
row--;
col = _size - 1;
}
break;
}
return row * _size + col;
}
//ColFirstMatrix.cpp
#include <iostream>
#include "Matrix.h"
using namespace std;
int ColFirstMatrix::findPosition(){
switch(dir){
case 'D'://列优先且向下且向右填充(左上角)
if(row < _size - 1 && _data[(row + 1) * _size + col] == 0)
row++;
else
if(col < _size - 1){
col++;
row = 0;
}
break;
case 'L'://列优先且向下且向左填充(右上角)
if(row < _size - 1 && _data[(row + 1) * _size + col] == 0)
row++;
else
if(col > 0){
col--;
row = 0;
}
break;
case 'R'://列优先且向上且向右填充(左下角)
if(row > 0 && _data[(row - 1) * _size + col] == 0)
row--;
else
if(col < _size - 1){
col++;
row = _size - 1;
}
break;
case 'U'://列优先且向上且向左填充(右下角)
if(row > 0 && _data[(row - 1) * _size + col] == 0)
row--;
else
if(col > 0){
col--;
row = _size - 1;
}
break;
}
return row * _size + col;
}
经验总结:
这个工程,编译器没有报错,测试结果却全盘错误。从中午十二点调试到现在晚上九点半。调试的心得和失败的原因如下。(我刚写在工程文件夹里的备忘录)
有些程序适合用结构化程序设计方法来做,或者结合一点面向对象的方法,但是过分地试图采用面向对象的技术,却会适得其反!chap5-001-2 的大段结构化程序、结合一点面向对象的方法,做得是多么好!而这个工程调了几乎一整天,依然像一团乱麻。造成混乱的中心问题是平级的派生类之间,参数不好传递,函数不好调用。同样是某个基类Base的派生类A1和A2,我用A1定义了对象,却需要用到A2中的成员函数;而A2的构造函数又需要从A1的对象得到初始化参数;而A1中开辟的内存空间却无法得到原本属于A2中的内存空间的数据。所以虽然没有语法错误,但是最终却输出的是大片为0的矩阵——因为调用的四个平级派生类的findPosition接口函数根本就没有把_data[]数组的值传递到main函数中定义对象所用的类Style的_data[]数组中来。这就像C语言中的goto语句一样混乱,像一团拎不清的意大利面条。
由此得到的经验就是:不要用一个派生类去调用平级的同源(派生自同一个基类)的派生类,否则就会造成上述混乱。应该结构化解决的问题,就直接结构化解决好了。