修复退货问题.警告:控件到达C++中非void函数的末尾
Fix a return issue.Warning: control reaches end of non-void function in C++
我知道这看起来可能是重复的,但其他问题没有我想要的答案。
template <class T>
T Queue<T>::pop_back()
{
try
{
if (empty())
throw "The Queue is empty!";
size--;
back= (back- 1 + max_size) % (max_size);
return queue[back];
}
catch (char* strException)
{
cerr << "Error: " << strException << endl;
}
}
我有上面pop_back函数的实现。每次删除元素时,都必须返回该元素。然而,每当它试图从空队列中弹出某个内容时,它都会说"在抛出'char const*'的实例后调用terminate"中止(堆芯转储)"
有什么技巧和建议可以解决这个问题?我在那里有一个尝试接球的盖帽,但没有多大帮助。函数必须从调用它的地方返回一些东西,或者停止并返回到main。
我正在寻找一种设计模式,这样我就可以在遇到这样的问题时使用它。基本上,当我需要退货,但没有什么可以退货时,我该怎么办?
谢谢。
您不应该在函数本身中捕获异常-异常应该用于将问题传达给调用方-他们应该知道在这种情况下什么是合理的处理。
函数必须从调用它的地方返回一些东西,或者停止并返回到main。
不完全如此——如上所述,它可以throw
,并从最紧密地包围它被调用的地方的catch()
块继续。
请记住,不想进行异常处理的调用者可以在决定尝试弹出之前轻松测试empty()
或size()
。。。所以CCD_ 5将异常返回给他们是非常合理的。
此外,不要抛出字符串文字。。。请改用std::runtime_error("...")
。原因在这里。
我正在寻找一种设计模式,这样我就可以在遇到这样的问题时使用它。基本上,当我需要退货,但没有什么可以退货时,我该怎么办?
如前所述,抛出异常是处理此问题的一种正常方式,尤其是对于像从空堆栈中弹出这样的情况。不过,更普遍的是,其他替代方案包括:
-
返回哨兵值
-
例如,如果容器存储
int
s,您可能能够返回0
、-1
或numeric_limits<int>::max
,或者对于std::string
s,可能返回一个空的,但最好的方法取决于客户端代码将容器放入的用途 -
对于模板化容器,很难知道
T
的值是否可以用于此操作——例如,如果T
是char
,并且二进制文件中的内容存储在容器中,则您可能想用作sentinel的任何字符值也可能出现在文件中;如果您无论如何都想尝试这种方法,通常最好要求调用方提供一个sentinel值作为模板参数或构造函数参数。
-
-
返回
std::optional<T>
(仍在等待标准化,但可能由某些编译器提供)或boost::optional<T>
-
如果
.first
为true
,则返回std::pair<bool, T>
,其中.second
仅为弹出值,表示成功 -
返回一个[smart]指针,但这很笨拙,因为您可能必须为弹出值的副本动态分配内存;智能指针有助于确保调用方
delete
稍后是对象 -
只需记录调用方必须首先检查
empty()
或size()
,并且assert
从pop_back
中确认容器不是空的-如果调用方不满足此"前提条件",则会停止程序 -
将接口更改为
bool pop_back(T& t)
,其中返回值表示成功,并且将设置调用者指定的T
参数。
这些都不值得称为"模式"——模式往往指更复杂、更高级的设计方面。
替换当前代码
template <class T>
T Queue<T>::pop_back()
{
try
{
if (empty())
throw "The Queue is empty!";
size--;
back= (back- 1 + max_size_) % (max_size);
return queue[back];
}
catch (char* strException)
{
cerr << "Error: " << strException << endl;
}
}
像这样的东西:
template< class Type >
auto Queue<Type>::pop_back()
-> Type
{
if( empty() ) { throw std::runtime_error( "The Queue is empty!" ); }
--size;
back = (back - 1 + max_size_) % (max_size_); // Note fix of name
return queue[back];
}
您想要将异常抛出给调用者。
在函数中使用异常,仅仅跳转到输出一些文本的代码(并且未能返回函数结果)是没有意义的。
顺便说一句,在上为成员标准化一个单一的命名约定是个好主意。max_size_
和max_size
的无意混合,很可能是一个错误,而且无论如何都是一个严重的缺陷,如果使用单一的命名约定,就不会发生这种情况。事实上,作为数据成员的back
与max_size_
不一致。
还要注意使用std::runtime_error
而不是字符串文字作为异常对象。这支持捕获std::exception
。您可能会发现其他一些标准异常类更适合,更能指示特定问题,但我通常只使用std::runtime_error
。
使用标准异常类是一个好主意的另一个原因是,在catch
中很容易指定错误的类型。
例如,代码中的catch
将不起作用:
#include <iostream>
using namespace std;
void foo()
{
try
{
throw "Blah blah!";
}
catch( char* s )
{
cout << "Caught exception internally in foo(): " << s << endl;
return;
}
}
auto main() -> int
{
try
{
foo();
}
catch( ... )
{
cout << "Failed to catch exception in foo()." << endl;
}
}
输出:
未能在foo()中捕获异常。
确切地说,问题是您尝试了catch块。
如果抛出异常,执行流将转到catch逻辑。它将打印您的语句,并且函数将在不返回值的情况下结束。
在catch块的末尾或函数的末尾重新抛出添加return
语句的异常(重新抛出似乎是最好的选择,因为您根本不处理该异常)。
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- 在c++类上调用void函数
- 为什么野牛仍在使用"int yylex(void)",却找不到"int yylex(YYS
- 在派生函数中指定void*参数
- C++为什么尽管我调用了void函数,它却不起作用
- 如何从void函数输出字符串
- 我应该使用什么来代替void作为变体中的替代类型之一
- 奇怪的结构&GCC&clang(void*返回类型)
- Arduino:for/while/if在void setup()或void loop()之前?——错误:之前需要不合格
- 为什么这个函数将"const char*"转换为"void* const"而不是"const void*"
- 引用一个已擦除类型(void*)的指针
- 将尾部调用void(i32,..)位转换为llvm::函数以获取FnAttribute
- 库函数需要一个 std::function<void(void)>,如何传入类函数?
- 如何将指针从一个void函数传递到另一个C++
- 为什么我在使用void函数时得到错误代码C2276
- void*到驱动程序中的UnicodeString
- 为什么在逗号分隔符上下文中将预增量的结果强制转换为void
- 指针没有更新它在void函数内部指向的值
- 修复退货问题.警告:控件到达C++中非void函数的末尾
- 控制到达bool函数中非void函数的结束