30/09/2018, 17:47

Hỏi cách hoạt động của hàm tạo sao chép (copy constructor)

Em có một vài câu hỏi mong mọi người giải đáp (bài toán đa thức).

  • Có phải DATHUC u(d); được chạy thì hàm constructor mặc định sẽ được gọi và gán các giá trị khởi tạo cho đối tượng u, sau đó d mới được truyền vào và sau đó hàm copy constructor mới hoạt động?
  • Sau bước sao chép thành công cho u thì lại cố tình tạo ra sự thay đổi giá trị các hệ số của d trong hàm copy constructor. Vậy tại sao khi in ra giá trị của d trong hàm main thì d vẫn bị thay đổi dù đã dùng const khi truyền? Có cách nào khi in d mà các hệ số đa thức không bị thay đổi không(vẫn có bước thay đổi hệ số trong hàm copy constructor ).
#include <iostream>
using namespace std;
class DATHUC
{
private:
	int n_m;//Bậc của đa thức
	int *arr_m;//Mảng chứa hệ số của đa thức
public:
	DATHUC();
	~DATHUC();
	DATHUC(const DATHUC &mang);//Copy constructor
	friend ostream& operator<<(ostream& os, const DATHUC &d);
	friend istream& operator>>(istream& is, DATHUC &d);
};
DATHUC::DATHUC()
{
	this->n_m = 0;
	this->arr_m = NULL;
}
DATHUC::~DATHUC()
{
	this->n_m = 0;
	delete this->arr_m;
}
DATHUC::DATHUC(const DATHUC &mang)
{
	n_m = mang.n_m;
	arr_m = new int[mang.n_m + 1];
	for (int i = 0; i <= n_m; i++)
	{
		arr_m[i] = mang.arr_m[i];
	}
	//do có const nên d không bị thay đổi
	//nhưng in d ở hàm main vẫn bị thay đổi
	for (int i = 0; i <= n_m; i++)
	{
		mang.arr_m[i] = 0;
	}
}
ostream& operator<<(ostream& os, const DATHUC &d)
{
	for (int i = 0; i <= d.n_m; i++)
	{
		os << d.arr_m[i] << " ";
	}
	return os;
}
istream& operator>>(istream& is, DATHUC &d)
{
	if (d.arr_m == NULL)
	{
		delete d.arr_m;
	}
	cout << "
Bac cua da thuc: ";
	cin >> d.n_m;
	d.arr_m = new int[d.n_m + 1];
	for (int i = 0; i <= d.n_m; i++)
	{
		cout << "He so bac " << i << ": ";
		is >> d.arr_m[i];
	}
	return is;
}
int main()
{
	DATHUC d;
	cin >> d;
	DATHUC u(d);
	cout << "Phan so d: " << d << endl;
	cout << "Phan so u: " << u << endl;
	system("pause");
	return 0;
}
viết 19:56 ngày 30/09/2018

khi truyền const DATHUC& d thì chỉ có d.n_m và d.arr_m là hằng, còn những giá trị trong mảng mà d.arr_m trỏ tới thì ko phải là hằng.

xài std::vector thì ko bị trường hợp này:

class DATHUC
{
public:
    DATHUC() : coefs() {}
    DATHUC(const DATHUC& d) : coefs(d.coefs)
    {
        for (size_t i = 0; i < d.coefs.size(); ++i)
            d[i] = 0; // báo lỗi: no match for 'operator[]'
    }
private:
    std::vector<int> coefs;
};

std::vector<int> có overload toán tử [], 1 phương thức trả về const int&, 1 phương thức trả về int&:

const int& operator[](size_t i)const;
int& operator[](size_t i);

vì truyền d là const& nên chỉ có phương thức trả về const int& là xài được, nên khi viết d[i] = 0; thì ko được, vì ko gán 0 cho const int& được.

cái lợi tốt hơn nữa là ko phải cấp phát bộ nhớ trực tiếp, ko phải viết new hay delete, nên ko cần dtor, thậm chí cũng chả cần copy ctor làm gì.

Đại Dương viết 19:49 ngày 30/09/2018

const đối với đối tượng được hiểu là chỉ có thể truy cập đến các hàm là const của một đối tượng mà thôi. Nhưng do tham số ‘d’ Ở TRONG PHẠM VI của lớp nên nó có thể truy xuất TRỰC TIẾP dữ liệu thuộc phần private của lớp. Nhưng bạn không thể truy xuất đến hàm thành viên không hằng của đối tượng đó được!
Bạn cho là một tham chiếu thì không được phép thay đổi đối tượng đúng k? Nhưng phải biết là ngoài phạm vi của lớp thì bạn đâu có thể truy xuất phần private được đâu =>Khi bạn chỉ có thể dùng các hàm thành viên để giao tiếp mà thôi.

Bài liên quan
0