C++ 类模板使用使用友元函数重载<<运算符的坑

博客介绍了在VisualStudio2022中遇到的C2248错误,该错误涉及Vector类的private成员访问。通过删除友元函数的类模板声明、使用usingnamespacestd以及添加友元函数的类型参数,解决了编译问题。修复后的代码在VS2022和VC2010下均能正常编译运行。
摘要由CSDN通过智能技术生成

开发平台:Microsoft Visual Studio 2022
错误提示:

C2248 “Vector::mBase”: 无法访问 private成员(在“Vector”类中声明) Project10 E:\Microsoft Visual Studio\code\Project10\Vector.hpp 72
C2248 “Vector::lenSize”: 无法访问 private成员(在“Vector”类中声明) Project10 E:\Microsoft Visual Studio\code\Project10\Vector.hpp 71

错误分析:这里的错误非常的无厘头,由于ostream使用了命名空间std的原因,而且以上代码在vc2010中完全可以过编译运行。

代码:
Vector.h

#pragma once
#include <iostream>

template<typename T>
class Vector {
	
public:
	Vector(int lenSize);
	Vector(const Vector& other);
	T& operator[](int index) const;
	Vector& operator=(const Vector& other);
	int getLenSize() const;

	~Vector();
	
	template<typename T>
	friend std::ostream& operator<<(std::ostream& cout, const Vector& other);  // 全局友元返回ostream实现  cout << a <<b,类内部友元只能 a<<cout

private:
	int lenSize;
	T* mBase;  // 数组数据指针
};

Vector.hpp

#include<string.h>  // memecpy_s

#include "Vector.h"

template<typename T>
Vector<T>::Vector(int lenSize) {
	if (lenSize > 0) {
		this->lenSize = lenSize;
		mBase = new T[lenSize];
		memset(mBase, 0, sizeof(T) * lenSize);
	}
}

template<typename T>
Vector<T>::Vector(const Vector<T>& other) {
	// 这里存在问题mBase出现野指针,可以不用释放因为这个时候对象刚创建还没分配堆区空间
	//if (mBase) {
	//	delete[] mBase;
	//	mBase = NULL;
	//	lenSize = 0;
	//}

	lenSize = other.lenSize;
	mBase = new T[lenSize];
	//memcpy(mBase, other.mBase, sizeof(T)* other.lenSize); void* desc目标地址, void* src源地址,size字节数
	for (int i = 0; i < lenSize; i++) {
		mBase[i] = other.mBase[i];
	}

}

template<typename T>
T& Vector<T>::operator[](int index) const{
	return mBase[index];  // *(mBase+index);
}

template<typename T>
Vector<T>& Vector<T>::operator=(const Vector<T>& other) {
	if (mBase) {
		delete[] mBase;
		mBase = NULL;
		lenSize = 0;
	}

	lenSize = other.lenSize;
	mBase = new T[lenSize];
	//memcpy(mBase, other.mBase, sizeof(T) * other.lenSize);
	for (int i = 0; i < lenSize; i++) {
		mBase[i] = other.mBase[i];
	}

	return *this;  // v1 = v2 = v3;
}

template<typename T>
int Vector<T>::getLenSize() const {
	return lenSize;
}

template<typename T>
Vector<T>::~Vector() {
	if (mBase) {
		delete[] mBase;
		mBase = NULL;
		lenSize = 0;
	}
}

template<typename T>
std::ostream& operator<<(std::ostream& cout, const Vector<T>& other) {
	for (int i = 0; i < other.lenSize; i++) {
		cout << other.mBase[i] << " ";
	}
	
	return cout;
}

main.cpp

#include <iostream>
#include "Vector.hpp"
int main() {
	Vector<float> v1(10);

	for (int i = 0; i < v1.getLenSize(); i++) {
		v1[i] = i*0.1f;
	}

	for (int i = 0; i < v1.getLenSize(); i++) {
		std::cout << v1[i] << std::endl;
	}


	Vector<float> v2 = v1;

	for (int i = 0; i < v2.getLenSize(); i++) {
		std::cout << v2[i] << std::endl;
	}
	
	Vector<float> v3(12);
	v3 = v2;

	for (int i = 0; i < v2.getLenSize(); i++) {
		std::cout << v3[i] << std::endl;
	}

	std::cout << v3 << std::endl;


	system("pause");
	return 0;
}

解决后的代码:

Vector.h

#pragma once
#include <iostream>
using namespace std;

template<typename T>
class Vector {
	
public:
	Vector(int lenSize);
	Vector(const Vector& other);
	T& operator[](int index) const;
	Vector& operator=(const Vector& other);
	int getLenSize() const;

	~Vector();
	
	// 1、此处删除类模板声明
	// 2、使用using namspace std;
	//3、operator<<后面加上虚拟参数列表<T>
	friend ostream& operator<< <T> (ostream& out, const Vector& other);  // 全局友元返回ostream实现  cout << a <<b,类内部友元只能 a<<cout

private:
	int lenSize;
	T* mBase = NULL;  // 数组数据指针
};

Vector.hpp

#include<string.h>  // memecpy_s

#include "Vector.h"

template<typename T>
Vector<T>::Vector(int lenSize) {
	if (lenSize > 0) {
		this->lenSize = lenSize;
		mBase = new T[lenSize];
		memset(mBase, 0, sizeof(T) * lenSize);
	}
}

template<typename T>
Vector<T>::Vector(const Vector<T>& other) {
	// 这里存在问题mBase出现野指针,可以不用释放因为这个时候对象刚创建还没分配堆区空间
	//if (mBase) {
	//	delete[] mBase;
	//	mBase = NULL;
	//	lenSize = 0;
	//}

	lenSize = other.lenSize;
	mBase = new T[lenSize];
	//memcpy(mBase, other.mBase, sizeof(T)* other.lenSize); void* desc目标地址, void* src源地址,size字节数
	for (int i = 0; i < lenSize; i++) {
		mBase[i] = other.mBase[i];
	}

}

template<typename T>
T& Vector<T>::operator[](int index) const{
	return mBase[index];  // *(mBase+index);
}

template<typename T>
Vector<T>& Vector<T>::operator=(const Vector<T>& other) {
	if (mBase) {
		delete[] mBase;
		mBase = NULL;
		lenSize = 0;
	}

	lenSize = other.lenSize;
	mBase = new T[lenSize];
	//memcpy(mBase, other.mBase, sizeof(T) * other.lenSize);
	for (int i = 0; i < lenSize; i++) {
		mBase[i] = other.mBase[i];
	}

	return *this;  // v1 = v2 = v3;
}

template<typename T>
int Vector<T>::getLenSize() const {
	return lenSize;
}

template<typename T>
Vector<T>::~Vector() {
	if (mBase) {
		delete[] mBase;
		mBase = NULL;
		lenSize = 0;
	}
}

template<typename T>
ostream& operator<<(ostream& out, const Vector<T>& other) {
	for (int i = 0; i < other.lenSize; i++) {
		out << other.mBase[i] << " ";
	}
	
	return out;
}

main.cpp

#include <iostream>
#include "Vector.hpp"

int main() {
	Vector<float> v1(10);

	for (int i = 0; i < v1.getLenSize(); i++) {
		v1[i] = i*0.1f;
	}

	for (int i = 0; i < v1.getLenSize(); i++) {
		std::cout << v1[i] << std::endl;
	}


	Vector<float> v2 = v1;

	for (int i = 0; i < v2.getLenSize(); i++) {
		std::cout << v2[i] << std::endl;
	}
	
	Vector<float> v3(12);
	v3 = v2;

	for (int i = 0; i < v2.getLenSize(); i++) {
		std::cout << v3[i] << std::endl;
	}

	std::cout << v3 << std::endl;

	return 0;
}

解决方法:

1、删除友元函数声明上面的类模板声明
2、使用using namspace std;,不用使用std::ostream
3、operator<<后面加上虚拟参数列表

以上代码在VS2022和VC2010中均可过编译运行

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

划水猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值