2012-02-19 11 views
8

私はC++を学んでいますが、私はオブジェクト指向の章に到達しました。 if文の中にオブジェクトを作成する方法について質問があります。条件付きのC++文でオブジェクトを作成

私が取り組んでいる問題は、レポートヘッダーを表示するクラスを作成するということです。このクラスには、会社名とレポート名を一般的なものに設定するデフォルトのコンストラクタがあり、ユーザーが望む場合は、2つの引数(文字列会社名とレポート名)を取るコンストラクタもあります。

問題は、「2つのパラメータのデフォルトのコンストラクタは、新しいReportオブジェクトが作成されるときにこれらの[会社名とレポート名]を指定できるようにする必要があります。ユーザーが引数を渡さずにReportオブジェクトを作成するとデフォルト値を使用します。それ以外の場合は、ユーザー指定の値を使用します。

私の質問は、これらのオブジェクトを作成する方法です。引数なしでオブジェクトを作成する方法を理解しています(newobj; Report)、また引数(Report newobj(string string);)も使用しています。基本的に、私はこれらのオブジェクトを最初に私の主な機能の先頭に作成する方法を得ます。しかし、ユーザの選択に基づいてif文をif文の中に作成することは可能ですか?ここで私はこれまで持っているものであると、明らかに、それは動作しません:

#include <iostream> 
#include <string> 
#include "report.h" 
using namespace std; 

bool enter_company_name();   // return true if user wants to enter company name 
bool print_form();    // return true if user wants to print in formatted output 

int main() 
{ 
    string company_name, 
    report_name; 
    bool name = false, 
    format = false; 

    name = enter_company_name(); 
    format = print_form(); 

    if (name) 
    { 
     cout << "Enter company name: "; 
     getline(cin, company_name); 
     cout << "Enter report name: "; 
     getline(cin, report_name); 
     Report header(company_name, report_name); // THIS IS MY PROBLEM 
    } 
    else 
     Report header; // THIS IS MY PROBLEM 

    if (format) 
    header.print_formatted(); 
    else 
    header.print_one_line(); 

    return 0; 
} 

bool enter_company_name() 
{ 
    char choice; 

    cout << "Do you want to enter a name?\n>"; 
    cin >> choice; 

    if (choice == 'y' || choice == 'Y') 
    return true; 
    else 
    return false; 
} 

bool print_form() 
{ 
    char choice; 

    cout << "Do you want to print a formatted header?\n>"; 
    cin >> choice; 

    if (choice == 'y' || choice == 'Y') 
    return true; 
    else 
    return false; 
} 

だから私はそれは選択だ場合は何も指定されていない場合、デフォルト値を使用してオブジェクトを作成したり、ユーザーの値を持つものを作成したいです与えられた。私はC++でインタラクティブに行う方法を理解できません。私は今までのところどこにも同様の質問を見つけることができませんでした。

私が遭遇した最も近いことは、私がやりたいことに似た何かをするためにポインタを使用していますが、私が使っている本はまだポインタに達していません。それは私が働いている章の範囲内にとどまります(つまり、ポインタを使わない)。

ヘッダーファイルやクラスの実装ファイルは、ここでは関係ないと思うので、私は含めませんでした。

ありがとうございます!

+0

これは、ポインタを使用できないときには本当に興味深い質問です!私はデフォルトの 'レポート'を作成せずにそれを後で上書きすることなく(愚かなように)きれいに行うことはできないかもしれないと思います。 –

+0

あなたはスコープの問題に遭遇しています - ここで似たような質問があり、誰かがポインタを使って答えます:http://stackoverflow.com/questions/1793807/declaring-a-variable-in-an-if-else-block-in -c - あなたのために、 'if'ステートメントの外側に' Report'オブジェクトを作成することができます。これはオブジェクトのデフォルトのコンストラクタを呼び出し、 'name'を取得した場合、別の'レポート'。もちろん、デフォルトのコンストラクタがない場合、このソリューションはうまくいかず、コンパイラはあなたに叫ぶでしょう。 – birryree

+0

@orangeoctopus:それは**可能であり、実際にはほんのわずかです。 –

答えて

7

あなたの質問を正しく理解しているかどうかわかりませんが、if/elseブロックの前にレポートを宣言して内部を初期化できませんか?

Report header; 

if (...) { 
    header = Report(); 
else 
    header = Report(name,company); 

か短いのように:もちろん

Report header; // calls default constructor 

if (shouldInitializeWithParams) { 
    header = Report(name,company); 
} 

これは、定義された空のコンストラクタを持っている必要があります。

+1

'header = Report();'行は 'Report header;'にする必要もなく、デフォルトコンストラクタを呼び出します。 – birryree

+0

はい、それは晴天のためでした。実際に初期化されるので、再初期化はまったく必要ではありません。 – Jack

+0

が真であり、実際には 'header'オブジェクトに' name'と 'company'フィールドを設定することができ、別の' Report'オブジェクトを構築することができます。 – birryree

2

クラスReportがコピー可能かどうかわからないので、ポインタを使用する方がよいでしょう。

Report * header; 

if (...) { 
    header = new Report(); 
else 
    header = new Report(name,company); 

// after all don't forget 
delete header; 

そしてもちろん、あなたは私が正しくあなたの質問を理解している場合はわからないこと

header->print_formatted(); 
+0

レポートがコピー可能であるかどうかを少なくともチェック*する方がよいでしょうか? –

+0

可能であれば、確認してください。私はできません:)申し訳ありません:)それはnikすることができます - 私は知らないので、良い答えは、私のために、コピーの問題を避けるためにポインタを使用することです。 –

+1

クラス 'Report'がコピー可能であるかどうか分からないので、' Report'だけを移動可能にする必要がある別の関数を使う方が良いでしょう。あなたがまだポインタを推奨しているのとは別に、生ポインタの代わりに 'std :: unique_ptr'を使います。 – Begemoth

0

ようheaderポインタを使用する必要があります。あなたが答えを読んで、そうであることに気づいた場合にはお詫び申し上げます。

しかし、主な戦略はコンストラクタのオーバーロードを利用することだと思います。つまり、パラメータが渡されなかった場合と、パラメータが渡された場合の両方のコンストラクタを定義します。 前者(既定のコンストラクターと呼ばれるもの)は、会社名とレポート名を既定値に初期化します。後者は、受け取ったパラメータを会社名とレポート名に割り当てます。

ポインタの使用については、 'レポート'(クラス)型のオブジェクトを '宣言'することで回避できます。たとえば、ヘッダ(オブジェクト)の配列を作成することができます。 そして、ユーザーが応答したときに「定義」することができます。

ポインタを使用することで、実行時(動的割り当て)ではすべてを実行しますが、配列を使用する場合(または多くのオブジェクトを宣言する場合)は量が固定されます。これは非効率的なことがあります。

+0

動的または静的割り当ては、間違ったコンテキストで使用すると非効率的になります。おかげさまで –

2

最も簡単なことは、コードフローで少しリファクタリングを実行することです。入力を処理し、構築されたオブジェクトを返す関数を作成します。

Report loadReport() { 
    if (user_input()) { 
     // read input 
     return Report(name,company); 
    } else { 
     return Report(); 
    } 
} 

次にmainから関数を呼び出します。デザインのわずかな変更は、ユーザー入力からReportを作成するという単一の責任を持つ関数の導入です。これは実際には関数として理にかなっています。

11

最初に、条件文の中でオブジェクトを作成して、条件文の後に使用することはできません。条件文の2つの枝はそれぞれスコープを作成し、その中で作成されたオブジェクトは枝の末尾を破棄します。つまり、あなたは別のアプローチを考え出す必要があります。最も簡単な方法は、必要に応じてオブジェクトを返す関数へのオブジェクトの作成を委任することはおそらくです:

Report makeReport() { 
    if (enter_company_name()) { 
     ... 
     return Report(name, company); 
    } 
    return Report(); 
} 

... 
Report report = makeReport(); 

別のアプローチは、conditonally Report一つの方法または別のものを作成するために、三項演算子を使用することです。

bool get_company_name = enter_company_name(); 
std::string name(get_company_name? read_name(): ""); 
std::string company(get_company_name? read_company(): ""); 
Report report = get_company_name? Report(name, company): Report(); 

これらのアプローチのすべてがReportクラスが実際にコピー可能であることを前提としています。

+0

Duh - 条件付きでオブジェクトを作成して他の場所で使用することはできないことを知っていたはずです。何らかの理由で、私はそれが他の変数とは何とか異なっていると思いました。私は実際に関数を使ってオブジェクトを返すというアプローチを試みましたが、おそらくそれが問題に取り組む最もクリーンで最も効率的な方法だと思います。しかし、以前はオブジェクトが再初期化されることに気付かず、コンストラクタにユーザー指定の値を渡してオブジェクトを作成する方法を理解できませんでした。 – nik

+0

+ 1dがIMHOとして受け入れられた答えより優れています。これは、デフォルトの 'ctor()'を必要とします。私はちょうど非デフォルトのctorを実行しました。これは条件付きで2組のargsの1つで呼び出され、それをあなたの方法で解決する必要がありました。 (その後、一時的なメンバを返すことでさらに一歩進んだ... heh)あなたが言ったように、これはコピー可能ですが、私にとってはコピーはOKですが、デフォルトの 'ctor()'はそうではありません。 –

関連する問題