c++ - 关于真正使用抽象类的问题
问题描述
我正在编写程序来处理不同类型的矩阵,例如稀疏矩阵等。现在我有一个称为 DOK 的矩阵类型的完整类,并决定我需要一个抽象类 Matrix 以在其他子矩阵中继承,并且我将能够应用所有具有不同类的虚拟操作。所以我做了 Base 类:
#include "Triplet.h"
#include <iostream>
using namespace std;
template<typename T>
class Matrix{
public:
virtual Matrix<T>& operator*=(const Matrix<T>& B) = 0;
virtual const Matrix<T>& operator*(const Matrix<T>& B) const = 0;
virtual Matrix<T>& operator-=(const Matrix<T>& B) = 0;
virtual const Matrix<T>& operator-(const Matrix<T>& B) const = 0;
virtual Matrix<T>& operator+=(const Matrix<T>& B) = 0;
virtual const Matrix<T>& operator+(const Matrix<T>& B) const = 0;
virtual T operator()(int i, int j) = 0;
virtual T operator()(int i, int j) const = 0;
[[nodiscard]] virtual int getSizeN() const = 0;
[[nodiscard]] virtual int getSizeM() const = 0;
[[maybe_unused]] virtual void insert(const Triplet<T> &Element) = 0;
[[maybe_unused]] virtual void print() const = 0;
};
template<typename T>
ostream& operator<<(ostream &os, const Matrix<T>& matrix) {
matrix.print();
return os;
}
Triplet.h是结构
template<typename T>
struct Triplet{
int i;
int j;
T b;
};
选项卡是
template<typename T>
T Tabs(T num){
if(num<T(0)) return -num;
else return num;
}
和子类 DOK:
#include "Matrix.h"
#include <map>
#include <iostream>
#include <vector>
#include <iterator>
#include "Triplet.h"
//#include "Solver.h"
#include "Tabs.h"
#include "cmath"
#include "gnuplot-iostream.h"
#include <utility>
using namespace std;
template<typename T>
T tolerance = T(1e-19);
template<typename T>
class DOK: public Matrix<T>{
private:
/*
* Dictionary of Keys, pair<int, int> is coordinates of non-zero elements,
* next int is value
*/
int size_n;
int size_m;
map<pair<int, int>, T> dict;
// int count;
public:
DOK(vector<Triplet<T>> &matrix, int n, int m){
this->resize(n, m);
this->fill(matrix);
}
DOK(int n, int m){
this->resize(n, m);
}
~DOK() = default;
void fill(vector<Triplet<T>> &matrix){
//this->count=matrix.size();
//cout<<"Input your coordinates with value in format \"i j val\" "<<endl;
for(int k = 0; k < matrix.size(); k++){
this->insert(matrix[k]);
}
}
void insert(const Triplet<T> &Element) override{
if(Element.i >= this->size_n){
this->size_n = Element.i+1;
}
if(Element.j >= this->size_m){
this->size_m = Element.j+1;
}
pair<int, int> coordinates = {Element.i, Element.j};
this->dict.insert(pair(coordinates, Element.b));
}
void resize(int n, int m){
this->size_n=n;
this->size_m=m;
}
void print() const override {
cout<<endl;
for(int i = 0; i < this->size_n; i++){
for(int j = 0; j < this->size_m; j++){
if(this->dict.find({i, j})!= this->dict.cend()) cout<< fixed << setprecision(18)<<this->dict.find(pair(i, j))->second<<" "; else cout<<0<<" ";
}
cout<<endl;
}
}
void clearZeros(){
for(auto i = this->dict.begin(); i!=this->dict.end();){
if(Tabs(i->second) <= tolerance<T>){
i = this->dict.erase(i);
} else{
i++;
}
}
}
[[nodiscard]] int getSizeN() const override{
return this->size_n;
}
[[nodiscard]] int getSizeM() const override{
return this->size_m;
}
void clearZeros(){
for(auto i = this->dict.begin(); i!=this->dict.end();){
if(Tabs(i->second) <= tolerance<T>){
i = this->dict.erase(i);
} else{
i++;
}
}
}
DOK<T>& operator+=(const Matrix<T> &matrix) override {
try{
if(this->getSizeN() != matrix.getSizeN() || this->getSizeM() != matrix.getSizeM()) throw 1;
for(int i = 0; i < this->getSizeN(); i++) {
for (int j = 0; j < this->getSizeM(); j++) {
T c = this->operator()(i, j) + matrix(i, j);
if(Tabs(c) > tolerance<T>) this->insert({i, j, c}); else this->dict.erase({i, j});
}
}
return *this;
}
catch (int a) {
cout<<"Sizes of Matrices are different."<<endl;
}
}
const DOK<T>& operator+(const Matrix<T>& matrix) const override {
DOK<T> t = *this;
return move(t+=matrix);
}
DOK<T>& operator-=(const Matrix<T>& matrix) override {
try{
if(this->getSizeN() != matrix.getSizeN() || this->getSizeM() != matrix.getSizeM()) throw 1;
for(int i = 0; i < this->getSizeN(); i++) {
for (int j = 0; j < this->getSizeM(); j++) {
T c = this->operator()(i, j) - matrix(i, j);
if(Tabs(c) > tolerance<T>) this->insert({i, j, c}); else this->dict.erase({i, j});
}
}
return *this;
}
catch (int a) {
cout<<"Sizes of Matrices are different."<<endl;
}
}
const DOK<T>& operator-(const Matrix<T> &matrix) const override {
DOK<T> t = *this;
return move(t-=matrix);
}
DOK<T>& operator*=(const Matrix<T> &matrix) override {
try {
if(this->getSizeN() != matrix.getSizeN()) throw 1;
DOK<T> M = DOK(this->getSizeN(), matrix.getSizeM());
for (int i = 0; i < this->getSizeN(); i++) {
for (int j = 0; j < matrix.getSizeM(); j++) {
T a=0;
for(int k = 0; k<this->getSizeM(); k++){
if(this->operator()(i, k) != 0 && matrix(k, j) != 0){
a+=this->operator()(i, k)*matrix(k,j);
//cout<<a<<endl;
}
}
Triplet<T> m = {i, j, a};
M.insert(m);
}
}
this->clearZeros();
*this=M;
return *this;
}
catch (int a) {
cout<<"Wrong sizes of matrices to multiplication"<<endl;
}
}
const DOK<T>& operator*(const Matrix<T>& matrix) const override{
DOK<T> t = *this;
return t*=matrix;
}
T operator()(int row, int col) override{
if(this->dict.find({row, col}) != dict.end()) return this->dict.find({row, col})->second;
else return T(0);
}
T operator()(int row, int col) const override{
if(this->dict.find({row, col}) != dict.end()) return this->dict.find({row, col})->second;
else return T(0);
}
};
但是我遇到了一个问题,现在我无法创建 DOK 对象,因为 Matrix 是一个抽象类。所以如果我这样做了
DOK<double> Q = DOK<double>(...)
cout<<Q*Q;
它正在工作,但现在我不能这样做,一种可能的变体是取消引用指针
Matrix<double>* Q = new DOK<double>(...);
cout<<(*Q) * (*Q);
如何在不从指针引用重写代码的情况下修复它?
解决方案
推荐阅读
- ballerina - 如何在后台运行芭蕾舞演员服务?
- java - 线程内的 AWS S3 文件上传未完成
- javascript - 仅使用 Trirand Jqgrid (ASP.NET WebForms v5.2) 保留列排序和搜索过滤器?
- sql - 获取一行中每个值的百分比
- wordpress - get_the_category() wordpress 函数在更新核心版本后停止工作
- ruby - 使用 ruby 抓取动态内容
- c# - C# ASP.NET 错误响应不使用 GlobalConfiguration.Configuration.Formatters 设置
- c - 在不使用 AUTOCONF 的情况下,如何准确地找出 C 编译器支持的说明符(如果有):inline、__inline__ 或 __inline?
- html - 为什么 bootstrap 3 行不扩展以适应内容?
- php - 试图用 spout 写日期单元格