30/09/2018, 20:10

Thắc mắc cấp phát động và tạo đối tượng

#include <iostream>
#include <fstream>
#include <cstring>
#include "student.h"

#define max 100

using namespace std;

void ReadFile(Student** sv, int &soSV){
	ifstream file;
	file.open("sinhvien.txt");
	if(file.fail()){
		cout<<"Cannot open file!";
		return;
	}
	soSV = 0;
	while(!file.eof()){
		string str;
		getline(file,str);
		if(str.length()>0){
			string info[5];
			int n=0;
			int end = -1;
			while(str.length()>0){
				end = str.find("|",0);
				if(end>-1){
					info[n] = str.substr(0,end);
					str.erase(0,end+1);
				} else {
					info[n] = str;
					str.erase(0,str.length());
				}
				n++;
			}
			sv[soSV] = new Student(info[0], info[1], info[2], info[3], info[4]);
			soSV++;
		}
	}
	file.close();
}

int main() {
	int SoSV;
	Student** sv;
	sv = new Student*[max];
	for(int i=0;i<max;i++) sv[i] = new Student();
	ReadFile(sv, SoSV);
	cout<<"Hien thi danh sach sinh vien:"<<endl;
	for(int i=0; i<SoSV; i++){
		sv[i]->Display();
	}:joy:
	return 0;
}

student.h

#ifndef _STUDENT_H_
#define _STUDENT_H_

#include <cstring>
using namespace std;

class Student{
	private:
		string MaSV;
		string HoTen;
		string NgaySinh;
		string GioiTinh;
		string LopQL;
	public:
		Student();
		Student(Student&);
		Student(string, string, string, string, string);
		void Read();
		void Display();
};

#endif

student.cpp

#include <iostream>
#include <iomanip>
#include "student.h"

using namespace std;

Student::Student(){
	MaSV = "";
	HoTen = "";
	NgaySinh = "";
	GioiTinh = "";
	LopQL = "";
}
Student::Student(Student& sv){
	MaSV = sv.MaSV;
	HoTen = sv.HoTen;
	NgaySinh = sv.NgaySinh;
	GioiTinh = sv.GioiTinh;
	LopQL = sv.LopQL;
}
Student::Student(string masv, string hoten, string ngaysinh, string gioitinh, string lopql){
	this->MaSV = masv;
	this->HoTen = hoten;
	this->NgaySinh = ngaysinh;
	this->GioiTinh = gioitinh;
	this->LopQL = lopql;
}
void Student::Read(){
	cout<<"Ma SV: ";
	fflush(stdin);
	cin>>MaSV;
	cout<<"Ho ten: ";
	fflush(stdin);
	cin>>HoTen;
	cout<<"Ngay sinh: ";
	fflush(stdin);
	cin>>NgaySinh;
	cout<<"Gioi tinh: ";
	fflush(stdin);
	cin>>GioiTinh;
	cout<<"Lop QL: ";
	fflush(stdin);
	cin>>LopQL;
}
void Student::Display(){
	cout<<left<<setw(10)<<MaSV<<" | ";
	cout<<left<<setw(30)<<HoTen<<" | ";
	cout<<setw(10)<<NgaySinh<<" | ";
	cout<<left<<setw(3)<<GioiTinh<<" | ";
	cout<<left<<setw(6)<<LopQL<<endl;
}

E có thắc mắc là tại sao phải khởi tạo sv[i] = new Student(); bên ngoài rồi bên trong phải sv[soSV] = new Student(info[0], info[1], info[2], info[3], info[4]); mới chạy được. Nếu không nó sẽ không nhận được ô nhớ và crash.


Trời ơi, ai xem rồi có í kiến gì thì giúp e với.

Gió viết 22:11 ngày 30/09/2018

Ý kiến là file student kia có gì đặc biệt?

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

không có gì đặc biệt đâu, chỉ dùng 2 hàm khởi tạo là truyền và không truyền tham số với cái hàm hiển thị thôi. nó hoạt động tốt. nếu muốn chạy thử thì mình post lên cho. Sợ post dài mọi người ngại đọc nên mới ko đưa

Ngô Doãn Tuấn viết 22:18 ngày 30/09/2018

sv[i] = new Student(); bên ngoài rồi bên trong phải sv[soSV] = new Student(info[0], info[1], info[2], info[3], info[4])

Nếu không nhầm thì muốn khởi tạo phương thức khởi tạo truyền tham số, thì vẫn phải có phương thức khởi tạo mặc định trong class đó

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

Nếu không nhầm thì muốn khởi tạo phương thức khởi tạo truyền tham số, thì vẫn phải có phương thức khởi tạo mặc định trong class đó

trong lớp có rồi mà. nhưng tại sao phải khởi tạo đối tượng rồi bên trong hàm lại gán nó cho 1 đối tượng khác thì mới chạy được? mà không phải khởi tạo trong hàm luôn?

Ngô Doãn Tuấn viết 22:18 ngày 30/09/2018

Student** sv;

sv là đối tượng của Student.
Vậy Student là gì nhỉ
Khởi tạo bên ngoài là tạo ra đối tượng để gọi tới hàm [quote=“htwap, post:1, topic:23119”]
ReadFile(Student** sv
[/quote]
Còn

sv[soSV] = new Student(info[0], info[1], info[2], info[3], info[4]);

là phương tức khởi tạo có tham số
Class Student có chứa info[0], info[1], info[2], info[3], info[4]
Khi tạo đối tượng của Student thì nó cũng chứa các thuộc tính giống vậy.
Bác hỏi cứ hack não sao sao ấy. Em đọc hoài không hiểu
Chắc chưa tới lv này rồi
Em đi code tiếp.

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


Bác nói đúng ý code của e rồi đấy
Ý e muốn hỏi là tại sao phải khởi tạo sv[i] rồi bên trong hàm gán sv[i] cho đối tượng mới thì sv[i] mới mang giá trị, còn nếu không khởi tạo sv[i] bên ngoài hàm thì ra khỏi hàm nó sẽ không lưu lại giá trị mới gán vào .
Để e post bổ sung thêm mấy cái thư viện đã.

vũ xuân quân viết 22:14 ngày 30/09/2018

mục đích là viết code cho gọn.
Ở ngoài khởi tạo object sinhvien không có giá trị thuộc tính.
còn khởi tạo bên trong dùng để gán giá trị lại vào object.
Thay vì phải gán từng giá trị vào thuộc tính thì viết code kiểu này cho nhanh và gọn.

Cách viết này làm tốn bộ nhớ và tốn thời gian chạy chương trình.

Cách viết tốt nhất là bỏ chỗ khởi tạo bên ngoài để giảm thời gian chạy chương trình và giảm việc tạo rác vùng nhớ.

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

Cách viết tốt nhất là bỏ chỗ khởi tạo bên ngoài để giảm thời gian chạy chương trình và giảm việc tạo rác vùng nhớ.

nếu bỏ cái khởi tạo bên ngoài thì lỗi ạ, nó không lưu lại kết quả mình gán trong hàm kia ạ


À mà nếu bên trong e làm như thế này thì có thể bỏ đi cái khởi tạo bên ngoài ạ:

	Student *st = new Student(info[0], info[1], info[2], info[3], info[4]);
	sv[soSV] = *&st;

E biết rồi ạ, nếu mình khởi tạo bên trong hàm thì con trỏ mới được tạo ra sẽ bị hủy khi ra khỏi hàm, nhưng mà dữ liệu vẫn được ghi vào bộ nhớ rồi. nên là mình phải gán trực tiếp con trỏ của mình vào ô nhớ là giá trị của con trỏ tạo trong hàm chứ không phải gán cho nó địa chỉ của con trỏ mới tạo trong hàm.

Bài liên quan
0