Có nên dùng con trỏ this?

e viết thư viện như sau?
có cần thiết dùng con trỏ this ạ?

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

#define MAX 10

class MaTran
{
	public:
		MaTran(int m, int n);
		~MaTran();
		void inMaTran();
		void nhapMaTran();
		void chuyenVi();
		int dinhThuc(int p=0);
		float phuHop(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=MAX,soCot=MAX;
		float det=0;
		float **mt=new float*[soHang];
};

MaTran::MaTran(int m, int n){
	this->soHang=m;
	this->soCot=n;
	for(int i=0;i<this->soHang;i++)
		this->mt[i]=new float[this->soCot];
}

MaTran::~MaTran(){
	for(int i=0;i<this->soHang;i++) delete[] this->mt[i];
	delete[] this->mt;
	this->soHang=0; this->soCot=0;
	this->det=0;
}

void MaTran::inMaTran(){
	cout<<fixed<<setprecision(2);
	for(int i=0;i<this->soHang;i++){
		cout<<"\n\t";
		for(int j=0;j<this->soCot;j++) cout<<setw(4)<<this->mt[i][j]<<" ";
	}
	cout<<endl;
}

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

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

int MaTran::dinhThuc(int p){
	if(this->soHang==this->soCot){
		int i=0,d=0;
		float dt=1.0;
		//Tao ma tran B lay gia tri cua ma tran A
		MaTran b(this->soHang,this->soCot);
		for(int i=0;i<b.soHang;i++)
			for(int j=0;j<b.soCot;j++)
				b.mt[i][j]=this->mt[j][i];
		//Dua ma tran ve ma tran tam giac tren
		for(i=0;i<b.soHang-1;i++){
			if(b.mt[i][i]==0)
				for(int k=i+1;k<b.soHang;k++){
					bool c=0;
					if(b.mt[k][i]!=0){
						for(int j=0;j<b.soCot;j++){
							float t=b.mt[i][j];
							b.mt[i][j]=b.mt[k][j];
							b.mt[k][j]=t;
						}
						d++;
						c=1;
						break;
					}
					if(c) break;
				}
			for(int k=i+1;k<b.soHang;k++){
				double tl=b.mt[k][i]/b.mt[i][i];
				for(int j=0;j<soCot;j++)
					b.mt[k][j]-=b.mt[i][j]*tl;
			}
		}
		//Tinh dinh thuc bang tich cac phan tu tren duong cheo chinh
		for(i=0;i<b.soCot;i++) dt*=b.mt[i][i];
		if(dt!=0) dt*=pow(-1,d);
		this->det=dt;
		if(p) cout<<"\tDinh thuc cua ma tran A la: det(A) = "<<this->det<<endl;
		return 0;
	} else{
		return 1;
	}
}

float MaTran::phuHop(int hangXoa, int cotXoa){
	MaTran ph(this->soHang-1,this->soCot-1);
	for(int i=0;i<hangXoa;i++){
		for(int j=0;j<cotXoa;j++)
			ph.mt[i][j]=this->mt[i][j];
		for(int j=cotXoa;j<ph.soCot;j++)
			ph.mt[i][j]=this->mt[i][j+1];
	}
	for(int i=hangXoa;i<ph.soHang;i++){
		for(int j=0;j<cotXoa;j++)
			ph.mt[i][j]=this->mt[i+1][j];
		for(int j=cotXoa;j<ph.soCot;j++)
			ph.mt[i][j]=this->mt[i+1][j+1];
	}
	ph.dinhThuc(0);
	float pTu=(float) ph.det/this->det;
	if(pTu!=0)
		pTu*=pow(-1,hangXoa+cotXoa);
	return pTu;
}

void MaTran::nghichDao(){
	if(this->dinhThuc(0)==1 || this->det==0) cout<<"\tMa Tran A khong kha nghich\n";
	else{
		//Tao ma tran chuyen vi cua ma tran A
		MaTran cv(this->soCot,this->soHang);
		for(int i=0;i<cv.soHang;i++)
			for(int j=0;j<cv.soCot;j++)
				cv.mt[i][j]=this->mt[j][i];
		//Tao ma tran B co cac phan tu la ma tran phu hop cua ma tran chuyen vi
		MaTran b(this->soHang,this->soCot);
		cv.det=this->det;
		for(int i=0;i<b.soHang;i++)
			for(int j=0;j<b.soCot;j++)
				b.mt[i][j]=cv.phuHop(i,j);
		cout<<"Ma tran nghich dao cua ma tran A la:";
		b.inMaTran();
	}
}

int MaTran::hang(){
	//Tao ma tran B lay gia tri cua ma tran A
	MaTran b(this->soHang,this->soCot);
	for(int i=0;i<b.soHang;i++)
		for(int j=0;j<b.soCot;j++)
			b.mt[i][j]=this->mt[i][j];
	//Dua ma tran ve ma tran tam giac tren
	for(int i=0;i<b.soHang-1;i++){
		for(int j=i;j<b.soCot;j++){
			if(b.mt[i][j]==0)
				for(int k=i+1;k<b.soHang;k++)
					if(b.mt[k][j]!=0){
						for(int u=0;u<b.soCot;u++){
							float t=b.mt[i][u];
							b.mt[i][u]=b.mt[k][u];
							b.mt[k][u]=t;
						}
						break;
					}
			if(b.mt[i][j]!=0){
				for(int k=i+1;k<b.soHang;k++){
					double tl=(double) b.mt[k][j]/b.mt[i][j];
					for(int u=0;u<b.soCot;u++){
						b.mt[k][u]-=b.mt[i][u]*tl;
					}
				}
				break;
			}
		}
	}
	//Tim hang
	int r=0;
	for(int i=b.soHang-1;i>=0;i--){
		for(int j=0;j<b.soCot;j++)
			if(abs(b.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<"<<this->soHang+1<<") ban muon xoa: ";
		cin>>x;
	} while(x<1 || x>this->soHang);
	MaTran b(this->soHang-1,this->soCot);
	x--;
	for(int j=0;j<b.soCot;j++){
		for(int i=0;i<x;i++)
			b.mt[i][j]=this->mt[i][j];
		for(int i=x;i<b.soHang;i++)
			b.mt[i][j]=this->mt[i+1][j];
	}
	cout<<"Ma tran A sau khi xoa hang thu "<<x+1<<" la:";
	b.inMaTran();
}

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

void MaTran::congMaTran(){
	MaTran b(this->soHang,this->soCot);
	cout<<"Nhap ma tran B:\n";
	b.nhapMaTran();
	for(int i=0;i<b.soHang;i++)
		for(int j=0;j<b.soCot;j++){
			b.mt[i][j]+=this->mt[i][j];
		}
	cout<<"Tong cua 2 ma tran A va B la:";
	b.inMaTran();
}

void MaTran::truMaTran(){
	MaTran b(this->soHang,this->soCot);
	cout<<"Nhap ma tran B:\n";
	b.nhapMaTran();
	for(int i=0;i<b.soHang;i++)
		for(int j=0;j<b.soCot;j++){
			b.mt[i][j]=this->mt[i][j]-b.mt[i][j];
		}
	cout<<"Hieu cua 2 ma tran A va B la:";
	b.inMaTran();
}

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

void MaTran::nhanMT_MT(){
	int cotB=10;
	cout<<"Nhap so cot cua ma tran B: ";
	cin>>cotB;
	MaTran b(this->soCot,cotB);
	cout<<"\nNhap ma tran B:\n";
	b.nhapMaTran();
	MaTran c(this->soHang,b.soCot);
	for(int i=0;i<c.soHang;i++)
		for(int j=0;j<c.soCot;j++){
			c.mt[i][j]=0;
			for(int k=0;k<this->soCot;k++)
				c.mt[i][j]+=this->mt[i][k]*b.mt[k][j];
		}
	cout<<"Tich cua ma tran A va ma tran B la:";
	c.inMaTran();
}

Viết thì cũng tốt, không viết cũng không sao. Bởi vì khi chương trình của em được compile thì compiler sẽ tự động gắn con trỏ this vào các biến member của class.

1.Trường nào hợp nào bắt buộc phải dùng con trỏ this?

Khi có sự trùng lặp tên biến, giữa biến bên ngoài và biến member. Ví dụ như sau:

MaTran::MaTran(int soHang, int soCot){
	this->soHang=soHang;
	this->soCot=soCot;
	for(int i=0;i<this->soHang;i++)
		this->mt[i]=new float[this->soCot];
}

2.Trường hợp nào không bắt buộc phải dùng con trỏ this?

Khi không có sự trùng lặp tên biến

MaTran::MaTran(int m, int n){
	this->soHang=m;
	this->soCot=n;
	for(int i=0;i<this->soHang;i++)
		this->mt[i]=new float[this->soCot];
}

3.Sử dụng con trỏ this để trả về chính thực thể của class đó
Như trong ví dụ này, và ví dụ này ta return về con trỏ this để thực hiện phép tính + liên tiếp.

template <class T>
Number<T>& Number<T>::operator+=(const Number<T>& value)
{
    m_data = m_data + value.m_data;
    return *this;
}

4.Videos về con trỏ this

2 Likes

cái mục 3 này đau đầu quá a ơi. T.T

Bỏ mục 3 đi, về sau sẽ cần, chứ bây giờ thì chưa cần

P/S: Đã sửa :expressionless:

2 Likes

vâng thưa cháu. :laughing:

1 Like

Đối với bản thân thì mình thường dùng this để phân biệt biến bên trong phương thức và biến của class.
Bạn có thể sử dụng style của google http://google-styleguide.googlecode.com/svn/trunk/cppguide.html
Theo mình biết thì ở Facebook, người code sẽ review code chéo cho nhau, và code phải đúng theo một style chung, vừa kiểm tra giúp nhau, vừa học hỏi kỹ thuật lẫn nhau. Đó là cách làm hay và mỗi người nên tự áp dụng cho mình để trình bày khoa học.

2 Likes

e nghĩ là cứ để this như thế cho rõ ràng cũng đc a nhỉ

:laughing:
dính trong quote rồi a ơi. :smile:

Style của Google cũng không dùng this, theo như link của google thì mình không thấy thế.

http://google-styleguide.googlecode.com/svn/trunk/cppguide.html#Classes

Style của mình là khi nào conflict tên biến mới dùng, vì nó khá là phiên phức khi cứ phải ghi this->

1 Like

e tạo 1 obj mới trong function để lấy giá trị của obj đang làm việc và làm việc với obj thay thế đó. tránh thay đổi giá trị của obj gốc.
thế dùng this có đc khuyến khích ko a?

:smiley: ý mình là có thể chọn lựa 1 style nào đó chứ không viết bừa bãi, chứ có this hay ko là tùy mỗi người, tùy nơi người đó làm việc. Lúc mình làm thì chỗ nào this được thì để this, có một số qui tắc thì áp dụng theo google style :D. @ltd

1 Like

Em cho anh xem code mẫu được không? Giải thích của em chưa rõ lắm.

Ừ, mình cũng hay xem Google Style, mà có điều không hợp với mình lắm. Mình code C nhiêu hơn C++ nên bị nhiễm một ít C vào rồi. Với cả mình hay xem trên Code Complete nữa, đó cũng là một nguồn tốt. để xây dựng style coding cho mình.

2 Likes

code e post ở đầu bài đó a.
đề thì là tạo thư viện làm việc với ma trận.
tên các function ở code nói hết các việc cần làm rồi a.

Cụ thể là đoạn nào? Code em dài thế mà không nói rõ anh lười xem lắm.

1 Like

ví dụ:

float MaTran::phuHop(int hangXoa, int cotXoa){
	MaTran ph(this->soHang-1,this->soCot-1);
	for(int i=0;i<hangXoa;i++){
		for(int j=0;j<cotXoa;j++)
			ph.mt[i][j]=this->mt[i][j];
		for(int j=cotXoa;j<ph.soCot;j++)
			ph.mt[i][j]=this->mt[i][j+1];
	}
	for(int i=hangXoa;i<ph.soHang;i++){
		for(int j=0;j<cotXoa;j++)
			ph.mt[i][j]=this->mt[i+1][j];
		for(int j=cotXoa;j<ph.soCot;j++)
			ph.mt[i][j]=this->mt[i+1][j+1];
	}
	ph.dinhThuc(0);
	float pTu=(float) ph.det/this->det;
	if(pTu!=0)
		pTu*=pow(-1,hangXoa+cotXoa);
	return pTu;
}

mấy hàm e đều tạo obj mới để thao tác thay vì thao tác trên obj gốc mà a.
obj gốc có thể còn để thực hiện thao tác khác nữa nên không thể thay đổi đc.

Quả thực là anh không thấy em tạo object mới ở đâu cả. Em có thể giải thích cụ thể hơn không?

float MaTran::phuHop(int hangXoa, int cotXoa){
	MaTran ph(this->soHang-1,this->soCot-1);
	for(int i=0;i<hangXoa;i++){
		for(int j=0;j<cotXoa;j++)
			ph.mt[i][j]=this->mt[i][j];
		for(int j=cotXoa;j<ph.soCot;j++)
			ph.mt[i][j]=this->mt[i][j+1];
	}
	for(int i=hangXoa;i<ph.soHang;i++){
		for(int j=0;j<cotXoa;j++)
			ph.mt[i][j]=this->mt[i+1][j];
		for(int j=cotXoa;j<ph.soCot;j++)
			ph.mt[i][j]=this->mt[i+1][j+1];
	}
	ph.dinhThuc(0);
	float pTu=(float) ph.det/this->det;
	if(pTu!=0)
		pTu*=pow(-1,hangXoa+cotXoa);
	return pTu;
}

cái

MaTran ph(this->soHang-1,this->soCot-1);

đó a.
e tạo 1 ma trận mới với số hàng và số cột giảm đi 1 đơn vị lưu ma trận gốc đã xóa 1 hàng và 1 cột đc truyền ở tham số.
chứ e ko xóa ở ma trận gốc.

à, a Đạt thêm cái nút Markdown vào thanh công cụ ở trên khung nhập text này đi. mỗi lần post code lại phải google markdown rồi copy paste vào. T.T

Cách em làm không đúng hướng đối tượng. Không liên quan đến con trỏ this ở đây.

Đây không phải là cách hay để giải quyết vấn đề.

Bên trong một đối tượng để tạo một đối tượng khác là copy của đối tượng hiện tại.

Nếu em cần tái sử dụng object gốc như em nói

Thì em làm cái việc tạo object mới ở hàm main, hay bất cứ hàm nào sử dụng object của em. Đừng copy trong nội bộ class như thế.

Class chỉ làm một việc là thực thi tính năng X, tính năng Y. Không nên bao gồm cả việc “backup” dữ liệu như thế.

Markdown có gì phức tạp đâu mà phải google?

83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?