30/09/2018, 16:23

Xin nhận xét class Ma Trận trong C++

file header của e như sau:
matran.h

#include <iomanip>
#include <complex>
#include <iostream>
using namespace std;

#define MAX 10

class MaTran
{
	public:
		MaTran(int soHang, int soCot);
		~MaTran();
		void inMaTran(float a[][MAX],int soHang,int soCot);
		void nhapMaTran();
		void chuyenVi(int in);
		bool dinhThuc(int in);
		float phuHop(float a[][MAX],int hangXoa, int cotXoa);
		void nghichDao();
		int hang();
		void xoaHang();
		void xoaCot();
		void congMaTran();
		void truMaTran();
		void nhanMT_So();
		void nhanMT_MT();
	private:
		int soHang,soCot;
		float det;
		float mt[MAX][MAX];
};
 
MaTran::MaTran(int soHang, int soCot){
	this->soHang=soHang;
	this->soCot=soCot;
}

MaTran::~MaTran(){
	for(int i=0;i<MAX;i++)
		for(int j=0;j<MAX;j++)
			mt[i][j]=0;
	soHang=soCot=det=0;
}

void MaTran::inMaTran(float a[][MAX],int soHang,int soCot){
	cout<<fixed<<setprecision(2);
	for(int i=0;i<soHang;i++){
		cout<<"
	";
		for(int j=0;j<soCot;j++) cout<<setw(5)<<a[i][j]<<" ";
	}
	cout<<endl;
}

void MaTran::nhapMaTran(){
	for(int i=0;i<soHang;i++)
		for(int j=0;j<soCot;j++){
			cout<<"	Phan tu ["<<i+1<<","<<j+1<<"] = ";
			cin>>mt[i][j];
		}
	cout<<"Ma tran ban vua nhap la:";
	inMaTran(mt,soHang,soCot);
}

void MaTran::chuyenVi(int in=0){
	float cv[MAX][MAX];
	for(int i=0;i<soCot;i++){
		for(int j=0;j<soHang;j++)
			cv[i][j]=mt[j][i];
	}
	cout<<"Ma tran chuyen vi cua ma tran A la:";
	inMaTran(cv,soCot,soHang);
}

bool MaTran::dinhThuc(int in=0){
	if(soHang==soCot){
		//Dua ma tran ve ma tran tam giac tren
		int d=0; //Bien d: dem so lan doi 2 hang cua ma tran
		//B1: tim gia tri khac 0 dau tien cua moi cot cho vao duong cheo chinh
		for(int i=0;i<soHang;i++){
			if(mt[i][i]==0)
				//Neu phan tu mt[i][i]=0 thi tim phan tu khac 0 dau tien trong cot i roi doi cho 2 hang
				for(int k=i+1;k<soHang;k++){
					if(mt[k][i]!=0){
						for(int j=0;j<soCot;j++){
							float t=mt[i][j];
							mt[i][j]=mt[k][j];
							mt[k][j]=t;
						}
						d++;
						break; //Khi doi cho xong thi thoat ra, khong tim nua
					}
				}
			if(mt[i][i]!=0)
				//Neu phan tu mt[i][i]!=0 thi dua cac phan tu cot i phia duoi mt[i][i] ve 0
				for(int k=i+1;k<soHang;k++){
					double tl=mt[k][i]/mt[i][i]; //bien tl de tim ti le 2 hang
					for(int j=0;j<soCot;j++)
						mt[k][j]-=mt[i][j]*tl;
				}
			else{
				//Neu sau cac buoc tren ma phan tu mt[i][i]=0 thi dinh thuc cua ma tran = 0, ta dua ra ket luan va thoat ra.
				det=0;
				if(in==1) cout<<"	Dinh thuc cua ma tran A la: det(A)="<<det<<endl;
				return 1;
			}
		}
		//Tinh dinh thuc bang tich cac phan tu tren duong cheo chinh
		det=1.0;
		for(int i=0;i<soCot;i++) det*=mt[i][i];
		det*=pow(-1,d); //ham pow(x,n)=x^n
		if(in==1) cout<<"	Dinh thuc cua ma tran A la: det(A)="<<det<<endl;
		return 1;
	} else{
		return 0;
	}
}

float MaTran::phuHop(float a[][MAX],int hangXoa, int cotXoa){
	//Ma tran phu hop xoa di 1 hang va 1 cot
	MaTran ph(soHang-1,soCot-1);
	for(int i=0;i<hangXoa;i++){
		for(int j=0;j<cotXoa;j++)
			ph.mt[i][j]=a[i][j];
		for(int j=cotXoa;j<ph.soCot;j++)
			ph.mt[i][j]=a[i][j+1];
	}
	for(int i=hangXoa;i<ph.soHang;i++){
		for(int j=0;j<cotXoa;j++)
			ph.mt[i][j]=a[i+1][j];
		for(int j=cotXoa;j<ph.soCot;j++)
			ph.mt[i][j]=a[i+1][j+1];
	}
	ph.dinhThuc(); //tinh dinh thuc
	if(ph.det==0) return 0; //neu dinh thuc bang 0 thi phan tu phu hop se bang 0
	float pTu=(float) ph.det/det; //neu khong thi tinh phan tu phu hop bang thuong cua dinh thuc ma tran phu hop
	pTu*=pow(-1,hangXoa+cotXoa); //va dinh thuc ma tran can tim nghich dao nhan voi -1^(hangxoa+cotxoa).
	//if(abs(pTu)<0.01 && abs(pTu)>0) cout<<pTu*10000000000<<endl; //Kiem tra xem phan tu -0.00 co phai la do lam tron khong.
	return pTu;
}

void MaTran::nghichDao(){
	if(!dinhThuc() || det==0) cout<<"	Ma Tran A khong kha nghich
";
	else{
		dinhThuc();
		//Tao ma tran lay gia tri cua ma tran chuyen vi
		float cv[MAX][MAX];
		for(int i=0;i<soHang;i++)
			for(int j=0;j<soCot;j++)
				cv[i][j]=mt[j][i];
		//Ma tran co cac phan tu la ti le dinh thuc cua ma tran phu hop va dinh thuc ma tran A
		for(int i=0;i<soHang;i++)
			for(int j=0;j<soCot;j++)
				mt[i][j]=phuHop(cv,i,j);
		cout<<"Ma tran nghich dao cua ma tran A la:";
		inMaTran(mt,soHang,soCot);
	}
}

int MaTran::hang(){
	//Dua ma tran ve ma tran tam giac tren
	for(int i=0;i<soHang-1;i++){
		for(int j=i;j<soCot;j++){
			if(mt[i][j]==0)
				for(int k=i+1;k<soHang;k++)
					if(mt[k][j]!=0){
						for(int u=0;u<soCot;u++){
							float t=mt[i][u];
							mt[i][u]=mt[k][u];
							mt[k][u]=t;
						}
						break;
					}
			if(mt[i][j]!=0){
				for(int k=i+1;k<soHang;k++){
					double tl=(double) mt[k][j]/mt[i][j];
					for(int u=0;u<soCot;u++){
						mt[k][u]-=mt[i][u]*tl;
					}
				}
				break;
			}
		}
	}
	//Tim hang (dem hang chua phan tu != 0 co chi so lon nhat, chi so do chinh la hang cua ma tran
	int r=0;
	for(int i=soHang-1;i>=0;i--){
		for(int j=0;j<soCot;j++)
			if(abs(mt[i][j])!=0){
				r=i+1;
				break;
			}
		if(r>0) break;
	}
	return r;
}

void MaTran::xoaHang(){
	int x=0;
	do{
		cout<<"Nhap vao hang thu x (0<x<"<<soHang+1<<") ban muon xoa: ";
		cin>>x;
	} while(x<1 || x>soHang);
	x--;
	soHang--;
	for(int j=0;j<soCot;j++)
		for(int i=x;i<soHang;i++)
			mt[i][j]=mt[i+1][j];
	cout<<"Ma tran A sau khi xoa hang thu "<<x+1<<" la:";
	inMaTran(mt,soHang,soCot);
}

void MaTran::xoaCot(){
	int x=0;
	do{
		cout<<"Nhap vao cot thu x (0<x<"<<soCot+1<<") ban muon xoa: ";
		cin>>x;
	} while(x<1 || x>soCot);
	x--;
	soCot--;
	for(int i=0;i<soHang;i++){
		for(int j=x;j<soCot;j++)
			mt[i][j]=mt[i][j+1];
	}
	cout<<"Ma tran A sau khi xoa cot thu "<<x+1<<" la:";
	inMaTran(mt,soHang,soCot);
}

void MaTran::congMaTran(){
	float b[MAX][MAX];
	cout<<"Nhap ma tran B:
";
	for(int i=0;i<soHang;i++)
		for(int j=0;j<soCot;j++){
			cout<<"	Phan tu ["<<i+1<<","<<j+1<<"] = ";
			cin>>b[i][j];
		}
	cout<<"Ma tran ban vua nhap la:";
	inMaTran(b,soHang,soCot);
	for(int i=0;i<soHang;i++)
		for(int j=0;j<soCot;j++){
			mt[i][j]+=b[i][j];
		}
	cout<<"Tong cua 2 ma tran A va B la:";
	inMaTran(mt,soHang,soCot);
}

void MaTran::truMaTran(){
	float b[MAX][MAX];
	cout<<"Nhap ma tran B:
";
	for(int i=0;i<soHang;i++)
		for(int j=0;j<soCot;j++){
			cout<<"	Phan tu ["<<i+1<<","<<j+1<<"] = ";
			cin>>b[i][j];
		}
	cout<<"Ma tran ban vua nhap la:";
	inMaTran(b,soHang,soCot);
	for(int i=0;i<soHang;i++)
		for(int j=0;j<soCot;j++){
			mt[i][j]-=b[i][j];
		}
	cout<<"Hieu cua 2 ma tran A va B la:";
	inMaTran(mt,soHang,soCot);
}

void MaTran::nhanMT_So(){
	float x=1;
	cout<<"Nhap vao so x: ";
	cin>>x;
	for(int i=0;i<soHang;i++)
		for(int j=0;j<soCot;j++)
			mt[i][j]*=x;
	cout<<"Tich cua "<<x<<" voi ma tran A la:";
	inMaTran(mt,soHang,soCot);
}

void MaTran::nhanMT_MT(){
	float b[MAX][MAX];
	int cotB=10;
	cout<<"Nhap so cot cua ma tran B: ";
	cin>>cotB;
	int hangB=soCot;
	cout<<"
Nhap ma tran B:
";
	for(int i=0;i<hangB;i++)
		for(int j=0;j<cotB;j++){
			cout<<"	Phan tu ["<<i+1<<","<<j+1<<"] = ";
			cin>>b[i][j];
		}
	cout<<"Ma tran ban vua nhap la:";
	inMaTran(b,hangB,cotB);
	float tong[MAX][MAX]={};
	for(int i=0;i<soHang;i++)
		for(int j=0;j<cotB;j++){
			for(int k=0;k<soCot;k++)
				tong[i][j]+=mt[i][k]*b[k][j];
		}
	cout<<"Tich cua ma tran A va ma tran B la:";
	inMaTran(tong,soHang,cotB);
}

file main.php

#include "matran.h"

int main(){
	int soHang,soCot;
	cout<<"Nhap so hang cua ma tran A: ";
	cin>>soHang;
	cout<<"Nhap so cot cua ma tran A: ";
	cin>>soCot;
	MaTran a(soHang,soCot);
	cout<<"
Nhap ma tran A:
";
	a.nhapMaTran();
	cout<<"
+ Danh sach thao tac:
";
	cout<<"	Chuyen vi:	1| Dinh thuc:		2| Nghich dao:	3|";
	cout<<"
	Hang:		4| Xoa hang:		5| Xoa cot:	6|";
	cout<<"
	Cong ma tran:	7| Tru ma tran:		8|";
	cout<<"
	Ma tran x So:	9| Ma tran x Ma tran:	10|";
	cout<<"
	Ket thuc phien lam viec:	0
";
	while(true){
		int tt=0;
		cout<<"
+ Chon thao tac ma ban muon thuc hien (0->10): ";
		cin>>tt;
		cout<<endl;
		MaTran b(soHang,soCot);
		b=a;
		switch(tt){
			case 1: b.chuyenVi(1); break;
			case 2: if(!b.dinhThuc(1)) cout<<"	Ma tran khong hop le!
"; break;
			case 3: b.nghichDao(); break;
			case 4: cout<<"	Hang cua ma tran A la: "<<b.hang()<<endl; break;
			case 5: b.xoaHang(); break;
			case 6: b.xoaCot(); break;
			case 7: b.congMaTran(); break;
			case 8: b.truMaTran(); break;
			case 9: b.nhanMT_So(); break;
			case 10: b.nhanMT_MT(); break;
			default: tt=0; break;
		}
		if(tt==0) break;
	}
	return 0;
}

e không biết như thế đã ổn chưa ạ, a @ltd cho e nhận xét với

Sáng Béo viết 18:26 ngày 30/09/2018
MaTran::~MaTran(){
	for(int i=0;i&lt;MAX;i++)
		for(int j=0;j&lt;MAX;j++)
			mt[i][j]=0;
	soHang=soCot=det=0;
}

cái này có bị gì ko ạ?
e thấy nó hình như ko cần thiết
xem hộ e với mấy a ơi @ltd @david15894

viết 18:26 ngày 30/09/2018

Hàm hủy để như thế thì không cần thiết cho lắm. Có một số lưu ý sau: hàm hủy nên để là virtual. Hàm tạo thì nên viết thế này

MaTran::MaTran( int soHang, int soCot) :
soHang( soHang),
soCot( soCot)
{
   
}

Cuối cùng là nên phân ra file header riêng và file .cpp riêng.

Noname Nofame viết 18:36 ngày 30/09/2018
  1. Code không có tính mở rộng: chỉ xài được kích thước 10x10 là hết cỡ, không dùng được kiểu nào khác ngoài float
  2. Không có operator overload nên khó sử dụng
  3. Cấu trúc dữ liệu và thuật toán chưa tối ưu (thuật toán nhân). Tuy nhiên với kích thước 10x10 thì có tối ưu thuật toán cũng chả có ích gì.
  4. Các phép vào/ra còn quá tùy tiện:
    1. Tại sao lại phải in ma trận sau mỗi lần thực hiện các hàm cộng/trừ/nhân? Cứ thực hiện âm thầm rồi để người ta gọi hàm in lúc cần thiết có phải hay hơn không?
    2. Tại sao lại yêu cầu nhập các ma trận để cộng/trừ/nhân? Thiết kế các hàm đó lấy tham số là một ma trận khác rồi mới thực hiện phép tính.
    3. Nói chung là các phép xuất nhập chỉ nên xuất hiện ở trong các hàm xuất/nhập. Không nên cho vào các hàm tính toán.

Nếu làm cả một class Ma Trận chỉ để làm bài tập này thì cứ thực hiện theo kiểu hướng thủ tục còn hơn. Còn nếu muốn sử dụng class Ma Trận sau này nữa thì nên làm cho chuẩn.

Sáng Béo viết 18:27 ngày 30/09/2018

Code không có tính mở rộng: chỉ xài được kích thước 10x10 là hết cỡ, không dùng được kiểu nào khác ngoài float

Lúc đầu e định làm cấp phát động, nhưng nó cứ thay đổi giá trị ma trân gốc dù đã gán ma trận b=a để thao tác trên b. nên là e bỏ cấp phát động, làm mảng cứng.

Không có operator overload nên khó sử dụng

cái này e học trên mạng ko hiểu nên e ko dùng.
e ko biết làm ạ.

Cấu trúc dữ liệu và thuật toán chưa tối ưu (thuật toán nhân)

thuật toán nhân là e làm theo công thức trong sách giáo khoa mà a.

Các phép vào/ra còn quá tùy tiện:

vâng, cái này chắc là e sẽ khắc phục

cứ thực hiện theo kiểu hướng thủ tục

là sao ạ? e ko hiểu câu này lắm ạ

Sáng Béo viết 18:23 ngày 30/09/2018

hàm hủy nên để là virtual

tại sao phải dùng hàm ảo ạ?

Hàm tạo thì nên viết thế này

trước e có đọc thấy người ta làm thế, nhưng kết quả giống với cách gán trong {}
tại sao lại nên viết như vậy ạ?

Cuối cùng là nên phân ra file header riêng và file .cpp riêng.

có 1 file header và .cpp rồi à a.

viết 18:32 ngày 30/09/2018

Giải thích về hàm tạo, nếu em không init giá trị cho các thuộc tính trước khi vào thân hàm tạo thì bước 1: nó sẽ gán một giá trị bất kì nào đó cho biến đấy, bước 2, em vào thân hàm tạo và gán giá trị lần nữa, tổng cộng là 2 lần.

Về hàm hủy: em tạo 1 con trỏ base class để trỏ tới 1 đối tượng ở class được kế thừa. Khi em hủy con trỏ đó thì nó chỉ gọi hàm hủy của base class và không gọi hàm hủy của lớp được kế thừa. Như vậy có khả năng là memory leak.

VD:

Matrix *pMatrix = new MatrixXXX();
delete pMatrix;

Sẽ gọi hàm hủy của Matrix.

Noname Nofame viết 18:26 ngày 30/09/2018

Lúc đầu e định làm cấp phát động, nhưng nó cứ thay đổi giá trị ma trân gốc dù đã gán ma trận b=a để thao tác trên b. nên là e bỏ cấp phát động, làm mảng cứng.

Về vấn đề này thì cần viết lại operator=.

Cấu trúc dữ liệu và thuật toán chưa tối ưu (thuật toán nhân)

thuật toán nhân là e làm theo công thức trong sách giáo khoa mà a.

Khoan đã nói về thuật toán nhân. Ở bài này bạn sử dụng cấu trúc dữ liệu mảng hai chiều, điều này không hề hiệu quả, vì mỗi lần truy cập một phần tử nào đó đều phải cần thêm một phép nhân. VD: mt[i][j] tương đương với (mt + iMAX+j).
Giải pháp: sử dụng mảng một chiều.

cứ thực hiện theo kiểu hướng thủ tục

là sao ạ? e ko hiểu câu này lắm ạ

Tức là viết dưới dạng các hàm, không cần phải bọc trong một class.

Sáng Béo viết 18:30 ngày 30/09/2018

Về hàm hủy: em tạo 1 con trỏ base class để trỏ tới 1 đối tượng ở class được kế thừa. Khi em hủy con trỏ đó thì nó chỉ gọi hàm hủy của base class và không gọi hàm hủy của lớp được kế thừa. Như vậy có khả năng là memory leak.

cái này e không hiểu lắm ạ

Sáng Béo viết 18:27 ngày 30/09/2018

Về vấn đề này thì cần viết lại operator=.

operator e ko hiểu a ạ. nó cứ rắc rối thế nào ấy ạ.

Khoan đã nói về thuật toán nhân. Ở bài này bạn sử dụng cấu trúc dữ liệu mảng hai chiều, điều này không hề hiệu quả, vì mỗi lần truy cập một phần tử nào đó đều phải cần thêm một phép nhân. VD: mt[i][j] tương đương với (mt + iMAX+j).Giải pháp: sử dụng mảng một chiều.

e biết Mảng 2 chiều thực chất cũng là mảng 1 chiều, nhưng mà khi thao tác thì cũng phải nhân mới ra đc phần tử dòng khác chứ ạ?

Tức là viết dưới dạng các hàm, không cần phải bọc trong một class.

à, thầy giáo e bảo làm hướng đối tượng mới được cộng điểm thêm ạ.

viết 18:39 ngày 30/09/2018

nói chung em cứ hiểu là để việc hủy nó diễn ra ok nhất thì cần virtual ở đằng trước.

VD anh đã nêu ở dưới đó, MatrixXX là đối tượng kế thừa từ matrix, đối tượng em tạo ra có type là MatrixXX* nhưng con trỏ đến nó lại có type là Matrix*, dẫn đến việc gọi hàm hủy nó gọi vào hàm hủy của Matrix chứ không phải là MatrixXXX.

Noname Nofame viết 18:37 ngày 30/09/2018

[quote=“htwap, post:10, topic:3244”]

Khoan đã nói về thuật toán nhân. Ở bài này bạn sử dụng cấu trúc dữ liệu mảng hai chiều, điều này không hề hiệu quả, vì mỗi lần truy cập một phần tử nào đó đều phải cần thêm một phép nhân. VD: mt[i][j] tương đương với (mt + iMAX+j).Giải pháp: sử dụng mảng một chiều.

e biết Mảng 2 chiều thực chất cũng là mảng 1 chiều, nhưng mà khi thao tác thì cũng phải nhân mới ra đc phần tử dòng khác chứ ạ?[/quote]

Không phải lúc nào cũng cần làm việc đó.
Ví du phép trừ và cộng ma trận: chỉ cần một vòng lặp qua tất cả các phần tử là đủ. Với mảng 2 chiều thì cần 2 vòng lặp lồng nhau và thêm O(n^2) phép nhân. Phép nhân và các phép toán khác có thể cải tiến mà không cần phải truy cập theo cặp <hàng, cột>

Tức là viết dưới dạng các hàm, không cần phải bọc trong một class.

à, thầy giáo e bảo làm hướng đối tượng mới được cộng điểm thêm ạ.

Chương trình của bạn không phải là lập trình hướng đối tượng, nó chỉ là các thủ tục bọc trong một class. Hướng đối tượng là “đóng gói”, “kế thừa”, “đa hình”. Về hình thức thì nó có class nhưng bản chất thì có cũng được mà không có cũng được.

Noname Nofame viết 18:34 ngày 30/09/2018

Đây là mẫu của lớp Ma trận, bạn có thể điền code vào những chỗ cần điền:

#include <cstring>
#include <cassert>
#include <algorithm>
#include <iostream>
#include <iomanip>

template <typename T>
class MaTran;


template <typename T>
class MaTran
{
    int soHang;
    int soCot;
    int kichThuoc;
    T *_data;

public:
    MaTran(int soHang, int soCot) 
        : soHang(soHang), soCot(soCot), 
          kichThuoc(soHang*soCot), _data(new T[kichThuoc])
    {}

    MaTran(MaTran const &mt)
        : soHang(mt.soHang), soCot(mt.soCot),
          kichThuoc(mt.kichThuoc), _data(new T[kichThuoc])
    {
        std::memcpy(_data, mt._data, kichThuoc * sizeof(T));
    }

    virtual ~MaTran() {
       if(_data) delete _data;
    }

    // chồng toán tử =, dùng để gán ma trận
    MaTran& operator=(MaTran const &mt) {
        if (this != &mt) {
            soHang = mt.soHang;
            soCot = mt.soCot;
            kichThuoc = mt.kichThuoc;
            if (_data) delete _data;
            _data = new T[kichThuoc];
            std::memcpy(_data, mt._data, kichThuoc * sizeof(T));
        }
        return *this;
    }

    // Toán tử xuất <<
    friend
    std::ostream& operator<<(std::ostream& os, MaTran<T> const &mt) {
        os << std::fixed << std::setprecision(2);
        for (int i=0;i<mt.soHang;i++) {
            os <<"\n\t";
            T const *hang = mt._data + i*mt.soCot;
            for(int j=0;j<mt.soCot;j++)
               os <<std::setw(5)<< hang[j] << ' ';
        }
        os << std::endl;
        return os;
    }

    // Toán tử nhập >>
    friend
    std::istream& operator>>(std::istream& is, MaTran<T> &mt) {
        for (int i=0;i<mt.soHang;i++) {
            T *hang = mt._data + i*mt.soCot;
            for(int j=0;j<mt.soCot;j++) {
               if (&is == &std::cin)
                   std::cout << "\tPhan tu[" << i + 1 << "," << j + 1 << "] = ";
                   is >> hang[j];
            }
        }
        return is;
    }

    // nạp chồng toán tử +=
    MaTran& operator+=(MaTran const &mt) {
        assert(soHang == mt.soHang && soCot == mt.soCot);
        for (int i = 0; i != kichThuoc; ++i) _data[i] += mt._data[i];
        return *this;
    }

    // nap chồng toán tử +
    friend MaTran<T> operator+(MaTran<T> const &m1, MaTran<T> const &m2) {
        MaTran<T> tong = m1;
        tong += m2;
        return tong;
    }

    // Làm tương tự với các phép -, *

    // viết các hàm tính toán khác như chuyển vị, định thức, ...
};

Đoạn code để test lớp MaTran:

    int main() {
	MaTran<int> m1(3, 3), m2(3, 3);
	std::cin >> m1; 
	std::cout << "m1 = " << m1 << '\n';
	std::cin >> m2;
	std::cout << "m2 = " << m2 << '\n';
	
	std::cout << "MaTran<int> m3 = m1\n";
	MaTran<int> m3 = m1;
	std::cout << "m3 = " << m3 << '\n';
	
	std::cout << "m3 += m2\n";
	m3 += m2;
	std::cout << "m3 = " << m3 << '\n';
	
	std::cout << "m3 = m3 + m1 + m2\n";
	m3 = m3 + m1 + m2;
	std::cout << "m3 = " << m3 << '\n';
	
	return 0;
}

link ideone: http://ideone.com/JIwTpb

Có thể thấy là bây giờ sử dụng đối tượng ma trận rất đơn giản, y như các kiểu dữ liệu bình thường.
Bạn có thể thêm vào các hàm cần thiết vào lớp ma trận. Còn về bài tập thì các chức năng như in, yêu cầu nhập, … nên đưa ra các hàm ngoài thay vì cho vào lớp ma trận.

viết 18:31 ngày 30/09/2018

:d bạn @noname_nofame lập trình hệ thống à?

Noname Nofame viết 18:36 ngày 30/09/2018

Không, vẫn chưa đi làm ngày nào.

Sáng Béo viết 18:35 ngày 30/09/2018

nói chung em cứ hiểu là để việc hủy nó diễn ra ok nhất thì cần virtual ở đằng trước.

VD anh đã nêu ở dưới đó, MatrixXX là đối tượng kế thừa từ matrix, đối tượng em tạo ra có type là MatrixXX* nhưng con trỏ đến nó lại có type là Matrix*, dẫn đến việc gọi hàm hủy nó gọi vào hàm hủy của Matrix chứ không phải là MatrixXXX.

cái này video của a Đạt có.

Sáng Béo viết 18:30 ngày 30/09/2018

vâng, e cảm ơn a ạ, e sẽ cố phân tích cái bài của a.

Đoàn Anh Dũng viết 18:33 ngày 30/09/2018

Viết class không phải là hướng đối tượng là ý làm sao hả bạn. Mình không hiểu lắm

Bài liên quan
0