电影是一件大事,所以应该动态分配。
因此,使用智能指针。
下面的代码演示/证明了每个提议的函数签名如何支持返回加载的电影并检查它是成功还是失败,并以最自然的方式解释所提供的信息(特别是“电影”是电影)。
请注意,问题中的签名都是非常糟糕的设计™的示例。
right
但是,下面代码中命名空间中显示的签名是可以的:
#include <memory> // std::shared_ptr
#include <new> // std::nothrow
#include <stdexcept> // std::runtime_error
#include <string> // std::string
class MovieData
{
// Whatever
};
// *** A movie is a big thing, so it should be allocated dynamically. ***
// *** Therefore, use a smart pointer. ***
//
typedef std::shared_ptr< MovieData > Movie;
namespace a {
using std::string;
using std::nothrow;
Movie readMovie(string filename)
{
return 0?0
: filename == "succeed"? Movie( ::new(nothrow) MovieData )
: Movie();
}
bool test( string const& filepath )
{
Movie const m = readMovie( filepath );
return (m != nullptr);
}
}
namespace b {
using std::string;
using std::nothrow;
bool readMovie(string filename, Movie m)
{
if( filename != "succeed" || m == nullptr )
{
return false;
}
*m = MovieData();
return true;
}
bool test( string const& filepath )
{
Movie const m( ::new(nothrow) MovieData );
return readMovie( filepath, m );
}
}
namespace c {
using std::string;
using std::nothrow;
Movie readMovie(string filename, bool &status)
{
status = false;
if( filename != "succeed" )
{
return Movie();
}
Movie const result( ::new(nothrow) MovieData );
status = true;
return result;
}
bool test( string const& filepath )
{
bool result = false;
readMovie( filepath, result );
return result;
}
}
namespace d {
using std::string;
using std::nothrow;
bool readMovie(string filename, const Movie &m)
{
if( filename != "succeed" || m == nullptr )
{
return false;
}
*m = MovieData();
return true;
}
bool test( string const& filepath )
{
Movie const m( ::new(nothrow) MovieData );
return readMovie( filepath, m );
}
}
namespace e {
using std::string;
using std::nothrow;
bool readMovie(string filename, Movie &m)
{
if( filename != "succeed" )
{
return false;
}
m.reset( ::new(nothrow) MovieData );
return (m != nullptr);
}
bool test( string const& filepath )
{
Movie m;
return readMovie( filepath, m );
}
}
namespace f {
using std::string;
using std::nothrow;
Movie readMovie(string filename, bool status)
{
(void) status; struct status; // Intentionally not used.
if( filename != "succeed" )
{
return Movie();
}
return Movie( ::new(nothrow) MovieData );
}
bool test( string const& filepath )
{
return (readMovie( filepath, bool() ) != nullptr);
}
}
namespace right {
using std::wstring; // Using wide string supports nearly all Windows filenames.
using std::runtime_error;
Movie readMovie( wstring const& filepath )
{
if( filepath != L"succeed" )
{
throw std::runtime_error( "right::readMovie: failed because ..." );
}
return Movie( new MovieData );
}
bool test( wstring const& filepath )
{
try
{
readMovie( filepath );
return true;
}
catch( ... )
{
return false;
}
}
}
#define TEST( name, filename ) \
wcout << #name "::readMovie" << "( " << #filename << " ) " \
<< (name ::test( filename )? "succeeded" : "failed") << "." << endl;
#include <iostream> // std::wcout, std::endl
int main()
{
using std::wcout; using std::endl; using std::boolalpha;
wcout << boolalpha;
TEST( a, "succeed" );
TEST( a, "fail" );
wcout << endl;
TEST( b, "succeed" );
TEST( b, "fail" );
wcout << endl;
TEST( c, "succeed" );
TEST( c, "fail" );
wcout << endl;
TEST( d, "succeed" );
TEST( d, "fail" );
wcout << endl;
TEST( e, "succeed" );
TEST( e, "fail" );
wcout << endl;
TEST( f, "succeed" );
TEST( f, "fail" );
wcout << endl;
TEST( right, L"succeed" );
TEST( right, L"fail" );
}
输出(测试结果):
a::readMovie( "succeed" ) 成功。
a::readMovie("fail") 失败。
b::readMovie("succeed") 成功。
b::readMovie("fail") 失败。
c::readMovie( "succeed" ) 成功。
c::readMovie("fail") 失败。
d::readMovie("succeed") 成功。
d::readMovie("fail") 失败。
e::readMovie( "succeed" ) 成功。
e::readMovie("fail") 失败。
f::readMovie( "succeed" ) 成功。
f::readMovie("fail") 失败。
right::readMovie( L"succeed" ) 成功。
对::readMovie(L"fail") 失败。