映画は大きなものなので、動的に割り当てる必要があります。
したがって、スマート ポインターを使用します。
以下のコードは、提供された情報の最も自然な解釈(特に、「映画」は映画である) を使用して、提案されたすべての関数シグネチャが、ロードされた映画を返し、それが成功したか失敗したかを確認する方法を示しています。
質問の署名はすべて、Very Bad Design™ の例であることに注意してください。
right
ただし、以下のコードの名前空間に示されている署名は問題ありません。
一般に、Windows ファイル名をサポートします。
ロードが失敗した場合、呼び出し元のコードに (誤って) 再生するムービー オブジェクトがないことが保証されます。これは、失敗を示す例外をスローすることによって行われます。
への参照によって文字列を渡しますconst
(効率のため、および一般的な良い習慣として)。
#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" ) が成功しました。
right::readMovie( L"fail" ) が失敗しました。