01/10/2018, 15:37

Nạp chồng toán tử + với 2 objects khác kiểu dữ liệu của một class

Đề bài đây ạ:

  • Xây dựng lớp vector (đặt tên là TVector) có các thành phần
  • Các thuộc tính thành phần có kiểu BẤT KỲ (int, char, float, double): x, y, z
  • Có tối thiểu hai hàm tạo
  • Có các phương thức: Nhập dữ liệu từ bàn phím, xuất dữ liệu ra màn hình
  • Có phương thích tính độ lớn vector theo công thức (||v||=sqrt(x 2 +y 2 +z 2 ))
  • Nạp chồng hoặc viết hàm bạn các toán tử so sánh: >, >=, <, <=, ==, != để so sánh độ lớn các vector

^Em chỉ hỏi về toán tử + thôi, các toán tử kia sẽ tự làm. Vấn đề ở đây là vector v1 có kiểu dữ liệu int, còn v2 với v3 kiểu float. Nếu v1 là float thì code ở dưới của em tự code chạy ổn không vấn đề gì, nhưng mà v1 lại có kiểu int nên khi chạy bị lỗi:
Error C244: “cannot convert from ‘TVector int’ to 'TVector float”
Ai giúp em với ạ!

#include <conio.h>
#include <iostream>
using namespace std;

template <class T>
class TVector
{
	T x, y, z;
public:
	TVector() : x{}, y{}, z{} { }
	TVector(T a, T b, T c)
	{
		x = a; y = b; z = c;
	}

	template <typename U>
	TVector operator+(TVector<U> vec)
	{
		TVector vec1;
		vec1.x = this->x + vec.x;
		vec1.y = this->y + vec.y;
		vec1.z = this->z + vec.z;
		return vec1;
	};

	void intput();
	void output()
	{
		cout << x << endl << y << endl << z;
	}
};

template <class T>
void TVector<T>::intput ()
{
	cout << "Nhap x: "; cin >> x;
	cout << "Nhap y: "; cin >> y;
	cout << "Nhap z: "; cin >> z;
}

int main()
{
	TVector<int> v1(5, 1, 33);
	TVector<float> v2(6.11, 6.1, 5.1);
	TVector<float> v3 = v1 + v2;

	v3.output();

	system("pause");
	return 0;
}
viết 17:47 ngày 01/10/2018

int và float khác kiểu tại sao lại cho phép cộng với nhau @_@

x, y, z là private, làm sao TVector<T> có thể truy cập TVector<U>::x hay TVector<U>::y hay TVector<U>::z được

TVector<T> + TVector<U> tại sao trả về kiểu TVector<T>? Lỡ T là int, U là float thì 1 + 1.1 trả về 2 à?

Trần Đức Hiếu viết 17:43 ngày 01/10/2018

Vì đề bài yêu cầu vector v1 có kiểu int, vector v2 có kiểu float? Chồng toán tử để cộng 2 vector ý mà.

Các thuộc tính thành phần có kiểu BẤT KỲ (int, char, float, double): x, y, z

x, y, z là private, làm sao TVector có thể truy cập TVector::x hay TVector::y hay TVector::z được

TVector + TVector tại sao trả về kiểu TVector? Lỡ T là int, U là float thì 1 + 1.1 trả về 2 à?

Ừ thì em đang vướng mắc chỗ này đó. A code giúp e với.

HK boy viết 17:41 ngày 01/10/2018

Các thuộc tính thành phần có kiểu BẤT KỲ (int, char, float, double)

Cho nó là double hết cũng đâu có chết ai đâu.

Bạn có thể cho x, y, z là public, hoặc vẫn để x, y, z là private và xây dựng các phương thức get_x, set_x, get_y, set_y, get_z, set_z để lấy/gán giá trị cho các phương thức.

Trần Đức Hiếu viết 17:38 ngày 01/10/2018

Đề bài nó bắt v1 là int . Chứ để cùng kiểu dữ liệu thì khỏi cần template luôn :).

HK boy viết 17:51 ngày 01/10/2018

Đã thế thì v3 làm quả chơi lầy, ép hết sang double =))

viết 17:53 ngày 01/10/2018
	TVector& operator+=(const TVector& rhs)
	{
		x += rhs.x;
		y += rhs.y;
		z += rhs.z;
		return *this;
	}
    
	TVector operator+(const TVector& rhs)const
	{
		TVector newVec = *this;
		newVec += rhs;
		return newVec;
	}

edit: thiếu constoperator+

vậy thôi là đủ rồi, bỏ cái <U> kia đi. Ở trong main thì kiểu int với float ko cộng được với nhau là đúng, v1 phải là TVector<float> luôn.

viết 17:39 ngày 01/10/2018

nếu em muốn TVector<T> + TVector<U> thì có nhiều cách, cách để cho người dùng tự quyết là tốt nhất, thêm 1 ctor nhận TVector<U> là được:

//khai báo lớp bạn trước
template <class U>
friend class TVector;

//ctor TVector<T> nhận TVector<U>
//explicit buộc người dùng ép kiểu tường minh bằng static_cast
template <typename U>
explicit TVector(const TVector<U>& vec)
    : x{static_cast<T>(vec.x)}
    , y{static_cast<T>(vec.y)}
    , z{static_cast<T>(vec.z)}
{
}

rồi ở dưới main xài:

TVector<float> v3 = static_cast<TVector<float>>(v1) + v2;
//hoặc
TVector<int> v4 = v1 + static_cast<TVector<int>>(v2);
viết 17:43 ngày 01/10/2018

kiểu ko khuyến khích là kiểu đi lấy kiểu chung giữa T và U, hay là kiểu mà T, U có thể implicit cast:

    template <class U>
    TVector<typename std::common_type<T,U>::type> operator+(const TVector<U>& rhs)const
    {
        TVector<typename std::common_type<T,U>::type> newVec;
        newVec.x = x + rhs.x;
        newVec.y = y + rhs.y;
        newVec.z = z + rhs.z;
        return newVec;
    }

//...

auto v5 = v1 + v2; //common_type của int và float là float, v5 là TVector<float>

viết v5 = v1 + v2 sạch đẹp hơn nhưng viết kiểu này làm vẫn có thể gây “lỗi”: kiểu float ko chứa hết tất cả giá trị của kiểu int được. Tốt hơn hết là để người dùng tự ép kiểu, họ phải tự hiểu rõ lỗi mất độ chính xác khi ép int về float.

Trần Đức Hiếu viết 17:39 ngày 01/10/2018

Em có một thắc mắc nhỏ thôi: Bên trong {} của explicit không viết gì cả ạ?

viết 17:48 ngày 01/10/2018

các biến của class có thể được khởi tạo trước khi vào thân hàm khởi tạo bằng cách xài dấu :, khi vào thân hàm khởi tạo thì x, y, z đã được khởi tạo hết rồi khỏi cần viết gì nữa

ABC(int a, double b, char c)
    : a(a), b(b), c(c)
{
    //a, b, c đã được khởi tạo ở trên
}

nếu em gán a, b, c bên trong {} thì thật ra trước đó a, b, c đã được khởi tạo với giá trị mặc định rồi, có thể hiểu là

ABC(int a, double b, char c)
{
    this->a = a;
    this->b = b;
    this->c = c;
}
//đồng nghĩa với 
ABC(int a, double b, char c)
    : a(0), b(0), c(0)
{
    this->a = a;
    this->b = b;
    this->c = c;
}

bưng cái khởi tạo lên : luôn, khỏi mất công viết this->

Bài liên quan
0