30/09/2018, 16:49

Lỗi khi tạo class trong C++

E compile ko thấy lỗi gì mà chạy lỗi sợ quá e debug thì thấy đến chỗ tạo class thì nó bị lỗi ạ. ai giúp e với ạ

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

class Monhoc{
      private:
              char* tenMon;
              float diemKT;
              float diemQT;
      public:
             Monhoc();
             Monhoc(const char* tenMon);
             Monhoc(Monhoc& mh);
             ~Monhoc();
             float tinhDiem();
             float getDiemQT();
             void setDiemQT(float diemQT);
             float getDiemKT();
             void setDiemKT(float diemKT);
             char* getTenMon();
             void setTenMon(char* tenMon);
};
Monhoc::Monhoc(){
	tenMon=new char[30];
         tenMon='';
         diemKT=0;
         diemQT=0;
}
Monhoc::Monhoc(const char* tenMon){
	tenMon=new char[30];
         strcpy(this->tenMon,tenMon);
         diemKT=0;
         diemQT=0;
}
Monhoc::Monhoc(Monhoc& mh){
	tenMon=new char[30];
         strcpy(tenMon,mh.tenMon);
         diemKT=mh.diemKT;
         diemQT=mh.diemQT;
}
Monhoc::~Monhoc(){
	delete[] tenMon;
}
float Monhoc::tinhDiem(){
      return diemQT*0.4+diemKT*0.6;
}
float Monhoc::getDiemQT(){
      return diemQT;
}
void Monhoc::setDiemQT(float diemQT){
     this->diemQT=diemQT;
}
float Monhoc::getDiemKT(){
      return diemKT;
}
void Monhoc::setDiemKT(float diemKT){
     this->diemKT=diemKT;
}
char* Monhoc::getTenMon(){
      return tenMon;
}
void Monhoc::setTenMon(char* tenMon){
     strcpy(this->tenMon,tenMon);
}


class SinhVien{
      private:
              int mssv;
              char* ten;
              Monhoc* dsmh;
              int tongSoMH;
              int soMonDaHoc;
      public:
             SinhVien();
             SinhVien(int ms, char* t);
             SinhVien(int ms, char* t, int tongMH, int soMonDaHoc);
             ~SinhVien();
             float tinhDiemTB();
             void addMonHoc(Monhoc& mh);
};
SinhVien::SinhVien(){
	ten=new char[50];
           mssv=0;
           ten='';
           tongSoMH=0;
           int soMonDaHoc=0;
}
SinhVien::SinhVien(int ms, char* t){
	ten=new char[50];
           mssv=ms;
           strcpy(ten,t);
           tongSoMH=0;
           int soMonDaHoc=0;
}
SinhVien::SinhVien(int ms, char* t, int tongMH, int soMonDaHoc=0){
	ten=new char[50];
           mssv=ms;
           strcpy(ten,t);
           tongSoMH=tongMH;
           dsmh=new Monhoc[tongSoMH];
           this->soMonDaHoc=soMonDaHoc;
}
SinhVien:: ~SinhVien(){
           if(tongSoMH>0) delete[] dsmh;
           delete[] ten;
}
float SinhVien::tinhDiemTB(){
    if(soMonDaHoc>0){
    	float tong=0;
	    for(int i=0;i<soMonDaHoc;i++)
	            tong+=dsmh[i].tinhDiem();
	    return tong/soMonDaHoc;
	} else return 0;
}
void SinhVien::addMonHoc(Monhoc& mh){
     if(soMonDaHoc<tongSoMH){
          dsmh[soMonDaHoc].setTenMon(mh.getTenMon());
          dsmh[soMonDaHoc].setDiemQT(mh.getDiemQT());
          dsmh[soMonDaHoc].setDiemKT(mh.getDiemKT());
          soMonDaHoc++;
     } else cout<<"Khong the them mon da hoc cho sinh vien nay do so mon da hoc da bang tong so mon hoc.
";
}

int main(){
    int n;
    SinhVien* sv=new SinhVien[50];
    cout<<"Tong so sinh vien:   ";
    cin>>n;
    for(int i=0;i<n;i++){
            char* ten;
			ten=new char[50];
            int tongMon=0, soMonDaHoc=0, mssv=0;
            cout<<"Nhap thong cho sinh vien "<< i+1<< endl;
            cout<<"	Ten: ";
            fflush(stdin);
            gets(ten);
            cout<<"	MSSV: ";
            cin>>mssv;
            cout<<"	Tong so mon hoc: ";
            cin>>tongMon;
            do{
                cout<<"	So mon da hoc: ";
                cin>>soMonDaHoc;
                if(tongMon<soMonDaHoc) cout<<"So mon da hoc phai <= Tong so mon hoc. Hay nhap lai!
";
            } while(tongMon<soMonDaHoc);
            sv[i]=SinhVien(mssv,ten,tongMon,soMonDaHoc);
            delete[] ten;
            cout<<"	Nhap diem cac mon:
";
            for(int j=0;j<soMonDaHoc;j++){
                    char* tenMH;
					tenMH=new char[30];
                    float diemKT=0, diemQT=0;
                    cout<<"		Mon thu "<<j+1<<endl;
                    cout<<"			Ten: ";
                    fflush(stdin);
                    gets(tenMH);
                    cout<<"			Diem QT: ";
                    cin>>diemQT;
                    cout<<"			Diem KT: ";
                    cin>>diemKT;
                    Monhoc mon;
                    mon.setTenMon(tenMH);
                    mon.setDiemQT(diemQT);
                    mon.setDiemKT(diemKT);
                    sv[i].addMonHoc(mon);
                    delete[] tenMH;
            }
    }
    cout<<"Diem trung binh cua cac sinh vien:
";
    for(int i=0;i<n;i++){
            cout<<"	Sinh vien thu "<< i+1<<": "<< fixed<< left<< setw(4)<< setprecision(2)<< sv[i].tinhDiemTB()<< endl;
    }
    system("pause");
    return 0;
}
... viết 18:56 ngày 30/09/2018

Chỉ góp ý về cách dùng cho copy constructor trong class MonHoc: http://www.learncpp.com/cpp-tutorial/912-shallow-vs-deep-copying/

Monhoc::Monhoc(){
	tenMon=new char[30];
         tenMon='\0';
         diemKT=0;
         diemQT=0;
}

Mình thấy dạo này nhiều người hay dùng kiểu khởi tạo cho kiểu char* như trên, cấp phát xong gán kí tự kết thúc xâu cho phần tử đầu tiên. Trước giờ mình không làm vậy, chưa test thử, ko biết dùng thế có sai không anh @ltd?

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

Chỉ góp ý về cách dùng cho copy constructor trong class MonHoc: http://www.learncpp.com/cpp-tutorial/912-shallow-vs-deep-copying/

Monhoc::Monhoc(){
tenMon=new char[30];
tenMon=’\0’;
diemKT=0;
diemQT=0;
}

Mình thấy dạo này nhiều người hay dùng kiểu khởi tạo cho kiểu char* như trên, cấp phát xong gán kí tự kết thúc xâu cho phần tử đầu tiên. Trước giờ mình không làm vậy, chưa test thử, ko biết dùng thế có sai không anh @ltd?

a xem e mấy chỗ này thế nào ạ?

sv[i]=SinhVien(mssv,ten,tongMon,soMonDaHoc);

sv[i].addMonHoc(mon);
... viết 18:58 ngày 30/09/2018

Hình như muốn gán

sv[i]=SinhVien(mssv,ten,tongMon,soMonDaHoc);

thì phải overloading operator = thì phải. Code block nó cảnh báo cái này trước khi chạy.
Anh @ltd đồn là class có thành phần là con trỏ thì cần có copy constructor và operator = :dizzy_face

Nó cảnh báo lớp Monhoc thiếu operator =
còn lớp Sinhvien thì thiếu copy constructor
Với lại trong các constructor, cái nào code block cũng cảnh báo là cần khởi tạo giá trị luôn cho biến sau khi new

Nguyễn Minh Dũng viết 18:51 ngày 30/09/2018

Ừ, đúng rồi. Bởi vì con trỏ chỉ là một biến lưu trữ địa chỉ của biến khác. Nếu em không có copy constructor và operator = thì làm sao em có thể gán hoặc khởi tạo một biến được?

Ví dụ như a có biết int thì anh cứ gán int x = 3. Nhưng với con trỏ thì anh phải biết kích thước nó như thế nào, vị trí ở đâu để gán chứ

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

thế e phải tạo 1 operator = để copy cái object này ạ. vâng, để e thử

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

Mình đã test rồi nhé:

Monhoc::Monhoc(){
	tenMon=new char[30];
         //tenMon='\0';
         diemKT=0;
         diemQT=0;
}

Xóa dòng gán kí tự kết thúc xâu cho vị trí đầu tiên của xâu sẽ không lỗi nữa.
Dạo này mình thấy nhiều người làm như thế này lắm.

P/s: Trong code block của mình cần thêm vào thư viện stdio.h để dùng cho hàm fflush(stdin), và thư viện windows.h dùng cho system(“pause”). Bạn coi bên phiên bản IDE của bạn có cần thì thêm vào luôn.
@htwap

Gió viết 19:02 ngày 30/09/2018

Mình nghĩ phần constructor Monhoc::Monhoc(const char* tenmon) bạn thay tenMon = this->tenMon ở dòng đầu tiên. Vì tenMonconst char* của hàm nên bị lỗi

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

Xóa dòng gán kí tự kết thúc xâu cho vị trí đầu tiên của xâu sẽ không lỗi nữa.Dạo này mình thấy nhiều người làm như thế này lắm.

vẫn bị lỗi a ơi, e phải thêm 1 cái cấp phát bộ nhớ cho tenMon vào hàm setTenMon() trong class Monhoc thì mới hết lỗi ạ.

P/s: Trong code block của mình cần thêm vào thư viện stdio.h để dùng cho hàm fflush(stdin), và thư viện windows.h dùng cho system(“pause”). Bạn coi bên phiên bản IDE của bạn có cần thì thêm vào luôn.@htwap

e dùng Dev C++, nó ko báo lỗi thiếu thư viện ạ

Mình nghĩ phần constructor Monhoc::Monhoc(const char* tenmon) bạn thay tenMon = this->tenMon ở dòng đầu tiên. Vì tenMon là const char* của hàm nên bị lỗi

Thank bạn, mình ko để ý chỗ này lắm, nhưng lúc khởi tạo ko gọi hàm này mà gọi 2 hàm khởi tạo là ko có tham số và có tham số là 1 class nên hàm có tham số là char* không được gọi. nên lỗi ko phải do cái này đâu…

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

ả nhí ổ, any bo đi hỉaaaaaaaaaaaa?

Bài liên quan
0