从 std::vector 的函数创建自定义扩展
Create Custom Extention from Function for std::vector
我正在尝试学习一些来自 C# 的 C++。我在 C# 中喜欢的一件事是像 CustomItem.ToString()
这样的扩展,并且很好奇我如何在 C++ 中实现类似的东西。我正在使用 std::vector<unsigned char>
来存储缓冲区,然后逐字节处理它。
我有以下功能:
int DataParser::ToLittleEndianInt(std::vector<unsigned char> ba) //Little Endian
{
long int Int = 0;
int arraySize = ba.size();
if (arraySize ==4)
{
Int = ba[0] | ((int)ba[1] << 8) | ((int)ba[2] << 16) | ((int)ba[3] << 24);
}
else if (arraySize == 2)
{
Int = ba[0] | ((int)ba[1] << 8);
}
else if (arraySize == 1)
{
Int = ba[0];
}
return Int;
}
在这里,我可以向它发送一个从 1 到 4 字节的向量,它会为我转换为整数。有没有办法让我像这样使用它:
std::vector<unsigned char> CurrentBytes(4);
for (int i = 0; i < 4; i++)
CurrentBytes[i]=1;
// how can we do this?
int results = CurrentBytes.ToLittleEndianInt();
//or
int results = CurrentBytes->ToLittleEndianInt();
我只是觉得它的可读性很好,希望对字符串、日期、int、美元等进行扩展。
更新:
我尝试按照建议进行自定义 class,但出现编译时错误。我把它放在我的 .h 文件中:
class Byte
{
public:
Byte();
~Byte();
std::string DataType;
int ColumnWidth;
std::vector<unsigned char> data;
int ToLEInt() {
long int Int = 0;
int arraySize = this->ColumnWidth;
if (arraySize == 2)
{
Int = this->data[0] | ((int)this->data[1] << 8);
}
else if (arraySize == 1)
{
Int = this->data[0];
}
return Int;
};
};
抛出错误:
Error LNK2019 unresolved external symbol "public: __thiscall Byte::Byte(void)" (??0Byte@@QAE@XZ) referenced in function "public: static void __cdecl DataParser::Parse(class nlohmann::basic_json<class std::map,class std::vector,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,bool,__int64,unsigned __int64,double,class std::allocator,struct nlohmann::adl_serializer>)" (?ParseToDataTable@Parse@@SAXV?$basic_json@Vmap@std@@Vvector@2@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@_N_J_KNVallocator@2@Uadl_serializer@nlohmann@@@nlohmann@@@Z)
我也尝试将其声明为:
const Byte& ToLEInt(const Byte& s)const {}
这是我在 Stephen Prata 的 C++ Primer 中看到的方法,但我仍然会出错,我必须在我的 cpp 中像这样使用它:
std::vector<unsigned char> test(3);
for (int i = 0; i < 2; i++)
test[i] = i;
Byte CurrentBytes;
CurrentBytes.data = test;
CurrentBytes.ColumnWidth=2;
int results = CurrentBytes.ToLEInt(CurrentBytes);
//instead of
int results = CurrentBytes.ToLEInt();
然后我尝试将声明放在 class 块之外,但随后我收到一个错误,指出 LEInt 未定义,
int Byte::ToLEInt(){}
当我尝试将 int ToLEInt();
添加到 class 块时,它会抱怨说它已经被定义了。
unresolved external symbol "public: __thiscall Byte::Byte(void)...
错误意味着链接器程序无法找到您的 class Byte
的构造函数的定义(主体)。为了解决这个问题,您可以在构造函数和析构函数声明中添加空括号(这次没有分号),如下所示:
class Byte
{
public:
Byte() {}
~Byte() {}
...
或者完全删除它们的声明,因为目前它们仍然处于空闲状态:
class Byte
{
public:
//Byte(); - can be removed entirely
//~Byte(); - can be removed entirely
...
当您不提供构造函数时,编译器会隐式生成默认构造函数,因此您不必担心它的声明或定义(正文)。但是,当您声明一个时,您需要自己提供它的定义(至少是空括号)。
// how can we do this?
int results = CurrentBytes.ToLittleEndianInt();
//or
int results = CurrentBytes->ToLittleEndianInt();
你不能。 C++ 不是那样工作的。
你可以做的是:
// assuming DataParser is a namespace
using namespace DataParser;
int results = ToLittleEndianInt(CurrentBytes);
// or...
int results = DataParser::ToLittleEndianInt(CurrentBytes);
这是 C++ 的处理方式。
如果你想要一个更优雅的解决方案,你可以从 std::vector
继承,尽管 this is not recommended.
更好的方法是创建自己的 class:
class myContainer {
private:
std::vector data;
public:
//...
int ToLittleEndianInt() {
// Process data...
return result;
}
};
那么您的代码将变为:
myContainer CurrentBytez;
//...
int results = CurrentBytes.ToLittleEndianInt();
当然,创建您自己的 class 需要一些研究,尤其是 C++ 与 C# 中的 classes 有何不同,但这可能是值得的。无论如何你可能想学习它,所以这没什么大不了的。
我正在尝试学习一些来自 C# 的 C++。我在 C# 中喜欢的一件事是像 CustomItem.ToString()
这样的扩展,并且很好奇我如何在 C++ 中实现类似的东西。我正在使用 std::vector<unsigned char>
来存储缓冲区,然后逐字节处理它。
我有以下功能:
int DataParser::ToLittleEndianInt(std::vector<unsigned char> ba) //Little Endian
{
long int Int = 0;
int arraySize = ba.size();
if (arraySize ==4)
{
Int = ba[0] | ((int)ba[1] << 8) | ((int)ba[2] << 16) | ((int)ba[3] << 24);
}
else if (arraySize == 2)
{
Int = ba[0] | ((int)ba[1] << 8);
}
else if (arraySize == 1)
{
Int = ba[0];
}
return Int;
}
在这里,我可以向它发送一个从 1 到 4 字节的向量,它会为我转换为整数。有没有办法让我像这样使用它:
std::vector<unsigned char> CurrentBytes(4);
for (int i = 0; i < 4; i++)
CurrentBytes[i]=1;
// how can we do this?
int results = CurrentBytes.ToLittleEndianInt();
//or
int results = CurrentBytes->ToLittleEndianInt();
我只是觉得它的可读性很好,希望对字符串、日期、int、美元等进行扩展。
更新:
我尝试按照建议进行自定义 class,但出现编译时错误。我把它放在我的 .h 文件中:
class Byte
{
public:
Byte();
~Byte();
std::string DataType;
int ColumnWidth;
std::vector<unsigned char> data;
int ToLEInt() {
long int Int = 0;
int arraySize = this->ColumnWidth;
if (arraySize == 2)
{
Int = this->data[0] | ((int)this->data[1] << 8);
}
else if (arraySize == 1)
{
Int = this->data[0];
}
return Int;
};
};
抛出错误:
Error LNK2019 unresolved external symbol "public: __thiscall Byte::Byte(void)" (??0Byte@@QAE@XZ) referenced in function "public: static void __cdecl DataParser::Parse(class nlohmann::basic_json<class std::map,class std::vector,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,bool,__int64,unsigned __int64,double,class std::allocator,struct nlohmann::adl_serializer>)" (?ParseToDataTable@Parse@@SAXV?$basic_json@Vmap@std@@Vvector@2@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@_N_J_KNVallocator@2@Uadl_serializer@nlohmann@@@nlohmann@@@Z)
我也尝试将其声明为:
const Byte& ToLEInt(const Byte& s)const {}
这是我在 Stephen Prata 的 C++ Primer 中看到的方法,但我仍然会出错,我必须在我的 cpp 中像这样使用它:
std::vector<unsigned char> test(3);
for (int i = 0; i < 2; i++)
test[i] = i;
Byte CurrentBytes;
CurrentBytes.data = test;
CurrentBytes.ColumnWidth=2;
int results = CurrentBytes.ToLEInt(CurrentBytes);
//instead of
int results = CurrentBytes.ToLEInt();
然后我尝试将声明放在 class 块之外,但随后我收到一个错误,指出 LEInt 未定义,
int Byte::ToLEInt(){}
当我尝试将 int ToLEInt();
添加到 class 块时,它会抱怨说它已经被定义了。
unresolved external symbol "public: __thiscall Byte::Byte(void)...
错误意味着链接器程序无法找到您的 class Byte
的构造函数的定义(主体)。为了解决这个问题,您可以在构造函数和析构函数声明中添加空括号(这次没有分号),如下所示:
class Byte
{
public:
Byte() {}
~Byte() {}
...
或者完全删除它们的声明,因为目前它们仍然处于空闲状态:
class Byte
{
public:
//Byte(); - can be removed entirely
//~Byte(); - can be removed entirely
...
当您不提供构造函数时,编译器会隐式生成默认构造函数,因此您不必担心它的声明或定义(正文)。但是,当您声明一个时,您需要自己提供它的定义(至少是空括号)。
// how can we do this? int results = CurrentBytes.ToLittleEndianInt(); //or int results = CurrentBytes->ToLittleEndianInt();
你不能。 C++ 不是那样工作的。
你可以做的是:
// assuming DataParser is a namespace
using namespace DataParser;
int results = ToLittleEndianInt(CurrentBytes);
// or...
int results = DataParser::ToLittleEndianInt(CurrentBytes);
这是 C++ 的处理方式。
如果你想要一个更优雅的解决方案,你可以从 std::vector
继承,尽管 this is not recommended.
更好的方法是创建自己的 class:
class myContainer {
private:
std::vector data;
public:
//...
int ToLittleEndianInt() {
// Process data...
return result;
}
};
那么您的代码将变为:
myContainer CurrentBytez;
//...
int results = CurrentBytes.ToLittleEndianInt();
当然,创建您自己的 class 需要一些研究,尤其是 C++ 与 C# 中的 classes 有何不同,但这可能是值得的。无论如何你可能想学习它,所以这没什么大不了的。