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;
}
Bài liên quan
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/
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 ạ?
và
Hình như muốn gán
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
Ừ, đú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ứthế e phải tạo 1 operator = để copy cái object này ạ. vâng, để e thử
Mình đã test rồi nhé:
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
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
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àmsetTenMon()
trong classMonhoc
thì mới hết lỗi ạ.e dùng Dev C++, nó ko báo lỗi thiếu thư viện ạ
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…
ả nhí ổ, any bo đi hỉaaaaaaaaaaaa?