我正在创建一个库。我想制作一个固定长度的字符串类。
#include <string>
#include <iostream>
#define OK 0
#define TOO_LONG 1
#define UNALLOWED_CHARACTERS 2
struct MyString {
MyString(int l)
: m_length(l) { }
struct exception {
exception(int t, MyString *p)
: type(t), ptr(p) { }
int type;
MyString *ptr;
};
int set(const std::string& name);
void set2(const std::string& name) throw(exception);
std::string m_str;
int m_length;
};
int MyString::set(const std::string& s)
{
if(s.size() > 64) {
return TOO_LONG;
} else if(s.find('~') != std::string::npos) {
return UNALLOWED_CHARACTERS;
} else {
m_str = s;
return OK;
}
}
void MyString::set2(const std::string& s) throw(exception)
{
if(s.size() > m_length) {
throw exception(TOO_LONG, this);
} else if(s.find('~') != std::string::npos) {
throw exception(UNALLOWED_CHARACTERS, this);
} else {
m_str = s;
}
}
int main()
{
using namespace std;
//OPTION 1
{
MyString s1(10);
MyString s2(10);
int code;
code = s1.set("abcdefghijX");
switch(code) {
case TOO_LONG:
//handle <--
break;
case UNALLOWED_CHARACTERS:
//handle
break;
default:
//ok!
break;
}
code = s2.set("abcdefghi~");
switch(code) {
case TOO_LONG:
//handle
break;
case UNALLOWED_CHARACTERS:
//handle <--
break;
default:
//ok!
break;
}
}
//OPTION 2
{
MyString s1(10);
MyString s2(10);
try {
s1.set2("abcdefghijX");
s2.set2("abcdefghi~");
} catch(MyString::exception &e) {
cerr << "MyString::exception: ";
auto p = e.ptr;
if(p == &s1) cerr << "s1 ";
else if(p == &s2) cerr << "s2 ";
switch(e.type) {
case TOO_LONG: cerr << "too long"; break;
case UNALLOWED_CHARACTERS: cerr << "unallowed characters"; break;
}
cerr << endl;
}
}
}
我不知道应该使用哪个版本的MyString :: set()。在这种情况下的惯例是什么?我在这个例子中使用STL进行演示。
答案 0 :(得分:1)
通常在C ++中,建议使用异常来指示当前上下文中无法恢复的错误。但这取决于目的。您可能希望在嵌入式环境中编译库,没有例外(为了提高效率),那么您必须使用返回码。
使用返回代码将API封装到使用异常的API很容易,反之亦然。
修改强>
有更多的理由说明为什么不使用异常处理可能有意义:
异常处理通常会引入有关放置在调用堆栈中所需的try/catch
块的其他信息,以及构建和检查这些信息时的一些性能损失。
答案 1 :(得分:1)
模仿标准库函数的行为是个好主意,除非有特殊原因不这样做。顺便说一句,因为tr1,STL内置了一个固定长度的字符串类。让我们看看它做了什么。我方便的唯一示例实现是Visual C ++ 2010。
std::tr1::array<int,5> arry;
arry[10] = 42; // Oopsie. There is no element 10.
编译并作为“Debug”版本运行时,我得到断言失败。当编译为“发布”时,攻击性声明悄然发生......没有。它的优化就不存在了。好吧,也许这并不总是人们想要的。忘记我所说的模仿STL,或者至少是微软的实现。意识火车继续......
我认为可以公平地说,如果程序试图设置超出范围的单元格,那就是程序中的逻辑错误。在任务关键型软件中,最好有代码来处理类似的情况并从中恢复,同时尝试确保它永远不会发生。
所以答案是,抛出类型为std :: out_of_range的异常。
所以那里。