Thắc mắc khi sử dụng con trỏ this trong C++

Chào anh chị em và các bạn trên diễn đàn, em mới học C++ , anh giảng viên có cho 1 ví dụ về cách sử dụng con trỏ this mà em nghĩ mãi vẫn chưa thực sự hiểu nên em muốn mọi người giúp em hiểu rõ bản chất của nó ạ .

Em muốn hỏi là :

  1. Thứ nhất, ở Phương thức RutGon , khi không sử dụng con trỏ this để thực thi phương thức RutGon mà anh gv lại tạo 1 đối tượng ps , sau đó làm việc trên đối tượng ps đó. Thì khi return ps;
    anh ấy giảng đoạn này là Giá trị của this->TuSo và this->MauSo không hề thay đổi .
    Và khi xuống dưới hàm main , để có thể sử dụng hàm RutGon và hàm Xuat và rút gọn đi giá trị được nhập vào từ hàm nhập thì phải tạo thêm 1 đối tượng ps2 để nhận cái return ps; của hàm RutGon trên kia thì code mới chạy
    em chưa hiểu cái đoạn return ps và xuống dưới tạo thêm ps2 để đón giá trị ps được return ạ
    và em muốn hỏi là ở phương thức RutGon thì return ps; là trả về cái gì ạ ? ( anh gv nói là trả về 1 cái đã thay đổi giá trị sau khi được rút gọn , nhưng " cái đó " là cái gì ạ ?)
    nếu đã trả về cái đã được thay đổi giá trị sau khi rút gọn tử số và mẫu số thì tại sao lại phải sử dụng ps2 ở hàm main ạ ???

  2. em muốn hỏi câu lệnh này có nghĩa gì ạ : a = abs(ps.TuSo);

em biết là em hỏi khá rắc rối vì thực sự em thấy đoạn ps và ps2 phức tạp quá ạ , nhưung mong mọi người giúp em , không hiểu được chắc đêm nay em mất ngủ :(((

đây là code ạ

#include <iostream>
using namespace std;
// Con trỏ this
// Con trỏ this tham chiếu đến đối tượng đang gọi hàm thành phần
class PhanSo{
    int TuSo, MauSo;
public:
    PhanSo RutGon();
    void Nhap();
    void Xuat();
};

// Cách dùng thứ 1 của Con trỏ this : trỏ(tham chiếu) đến các thành phần của class hiện tại
void PhanSo::Nhap(){
    cout<<"\n Nhap tu so : ";
    //cin>>TuSo;
    cin>>this->TuSo;
    cout<<"\n Nhap mau so : ";
    //cin>>MauSo;
    cin>>this->MauSo;
}

void PhanSo::Xuat(){
    cout<<this->TuSo<<"/"<<this->MauSo;
}

// Không dùng This nữa mà tạo đối tượng PS

PhanSo PhanSo::RutGon(){
    int a,b;
    PhanSo ps;
    ps.TuSo=this->TuSo;
    ps.MauSo=this->MauSo;
//Hàm tìm UCLN thông thường
    a = abs(ps.TuSo);
    b = abs(ps.MauSo);
    while(a!=b){
        if(a>b){
            a=a-b;
        }
        else{
            b=b-a;
        }
    }
    ps.TuSo=TuSo/a;
    ps.MauSo=MauSo/a;
    // Giá trị của this->TuSo và this->MauSo không hề thay đổi
    return ps; // Trả về giá trị của cái Class hiện tại
}


int main(){
    PhanSo ps,ps2;
    ps.Nhap();
    ps2=ps.RutGon(); // ps.TuSo và ps.MauSo không hề thay đổi, chỉ trả về 1 ps đã thay đổi
    //ps hoàn toàn không thay đổi
    ps2.Xuat();
    return 0;
}

lấy giá trị tuyệt đối
Tiếp theo là doituong.phuongthuc thì this.-> là thuộc tính của thằng doituong
ps2=ps.RuGon() trong phương thức RutGon khong dùng this nên ps ko thay đỏi gì, tạo ra 1 thắng ps rồi gán gt cho nó để return nên ps2 sẽ mang giá trị ps đấy

1 Like

anh ơi , khi return ps;
thì nó sẽ trả lại giá trị của class hiện tại . Giá trị đó chính là giá trị của TuSo và MauSo đúng không ạ ?

nó trả về gt của thằng PS chứ không phải class hiện tại(PS là 1 class mới)

1 Like

Theo như mình hiểu thì bạn đang thắc mắc về cách hoạt động của từ khóa return

Bạn cứ tưởng tượng khi khai báo PhanSo ps, ps2 thì psps2 là hai cái thùng trong máy tính, mỗi thùng chứa 2 tờ giấy là TuSoMauSo, 2 tờ giấy này không ghi gì cả. Sau đó bạn gọi phương thức ps.Nhap() thì máy tính sẽ bắt đầu ghi dữ liệu vào 2 tờ giấy TuSoMauSo trong thùng ps.

Tiếp theo khi bạn gọi phương thức ps.RutGon(), bên trong phương thức này lại có 1 khai báo khác là PhanSo ps thì máy tính lại tạo một cái thùng có 2 tờ giấy trắng TuSoMauSo khác và cái thùng ps này không liên quan gì đến cái ps được tạo ra ở hàm main cả, bản thân cái ps được tạo trong RutGon() sẽ bị máy tính xóa đi sau khi kết thúc lệnh return. Ở đây mình gọi tắt là psRutGonps để dễ phân biệt một tí nhé.

Bên trong phương thức RutGon() bạn có gọi
ps.TuSo=this->TuSo;
ps.MauSo=this->MauSo;
Hai dòng này tương đương với:
psRutGon.TuSo = ps->TuSo;
psRutGon.MauSo = ps->MauSo;
(mình chỉ viết như vậy cho dễ hiểu chứ ghi như thế là sai nhé)
Tức là 2 tờ giấy TuSoMauSo bên trong cái thùng psRutGon được tạo ra bên trong phương thức RutGon() giờ đây có giá trị bằng với 2 tờ giấy trong thùng ps ở hàm main, rồi sau đó là quá trình rút gọn phân số bla bla…

Sau khi đã rút gọn xong, câu lệnh cuối cùng là return ps; bản thân máy tính sẽ không xóa cái thùng psRutGon như mình nói ở trên mà nó chỉ quên đi cái thùng đó thôi, còn cái thùng thực chất vẫn nằm đâu đó trong máy tính. Do đó bạn phải có câu lệnh ps2 = ps.RutGon() để lưu lại thông tin của cái thùng đó trong ps2.

Đến đây là hiểu rồi chứ? :slight_smile:

Lưu ý: mình không biết C++ đến bây giờ có cho phép hay không nhưng đoạn gán dữ liệu theo mình nhớ phải là
ps.TuSo = this.TuSo;
ps.MauSo = this.MauSo;
Toán tử -> chỉ dành cho con trỏ, nếu muốn dùng toán tử này thì bạn phải khai báo là PhanSo *ps trong hàm main.
Update: mình nhầm, tuy khai báo không phải là con trỏ nhưng this là một con trỏ đặc biệt nên vẫn phải dùng toán tử -> nhé.

Còn hàm abs() là lấy giá trị tuyệt đối thôi, không có gì phức tạp. Vd abs(-5) = 5; abs(5) = 5

2 Likes

Nhiều khi lập trình viên cũng nên biết qua tiếng Anh và cách tra cứu hàm nhỉ.
abs = absolute, nghĩa là lấy giá trị tuyệt đối (tên hàm thường hay rút gọn thành 3 chữ)

Và theo thiển ý của mình, cũng nên đặt tên hàm / comment bằng tiếng Anh cho quen. Dùng tiếng Việt sau phát triển sản phẩm, những người maintain không phải dev Việt sẽ không hiểu gì luôn.

C++ object thì phải dùng . chứ (chưa gõ lại nhưng chắc code này không chạy).
-> chỉ dành cho pointer.

1 Like

em cám ơn các anh rất nhiều ạ , em đi học cả ngày giờ mới về nhà , qua sự giúp đỡ của các anh em đã hiểu thêm được phần nào rồi ạ

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