Создавать объекты в условных операторах c ++ - PullRequest
12 голосов
/ 19 февраля 2012

Я изучаю c ++, и я только что попал в объектно-ориентированную главу.У меня есть вопрос о создании объектов внутри операторов if.

Проблема, над которой я работаю, заключается в создании класса, который будет отображать заголовок отчета.Класс имеет конструктор по умолчанию, который задает имя компании и имя отчета в общем виде, а также, если пользователь хочет, имеет конструктор, который принимает два аргумента (строковое имя компании и имя отчета).

Проблема, в частности, гласит: «Конструктор по умолчанию с двумя параметрами должен позволять указывать эти [названия компаний и отчетов] при создании нового объекта отчета. Если пользователь создает объект отчета без передачилюбые аргументы, используйте значения по умолчанию. В противном случае, используйте указанные пользователем значения для имен. "

Итак, мой вопрос, как создать эти объекты?Я понимаю, как создать объект без каких-либо аргументов (например, Report newobj;), а также с аргументами (например, Report newobj (string string);).По сути, я понимаю, как создать эти объекты в начале моей основной функции.Но возможно ли создать их внутри, если утверждения основаны на выборе пользователя?Вот что у меня есть, и, очевидно, это не работает:

#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 ++.До сих пор я не смог найти ни одного подобного вопроса.

Самая близкая вещь, с которой я столкнулся, использует указатели, чтобы сделать что-то похожее на то, что я хочу сделать, но книга, которую я использую, еще не дошла до указателей, и я хочу попытаться выяснитьспособ сделать это, не выходя за рамки главы, в которой я работаю (т.е. не используя указатели).

Я не включил файл заголовка или файл реализации класса, потому что я не думаю, что ониАктуально здесь.

Заранее спасибо!

Ответы [ 6 ]

15 голосов
/ 19 февраля 2012

Во-первых, вы не можете создать объект в условном операторе и использовать его после условного оператора: две ветви условного оператора создают область действия каждый, и любой объект, созданный внутри, уничтожается в конце ветви.То есть вам нужно придумать другой подход.Самый простой подход, вероятно, состоит в том, чтобы делегировать создание объекта функции, которая возвращает объекты соответствующим образом:

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

...
Report report = makeReport();

Альтернативный подход заключается в использовании троичного оператора для условного создания 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 действительно копируемый.

9 голосов
/ 19 февраля 2012

Не знаю, правильно ли я понял ваш вопрос, но разве вы не можете просто объявить отчет перед блоком if / else и затем инициализировать его внутри?

Report header;

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

Или более коротким способом:

Report header; // calls default constructor

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

Конечно, для этого необходимо определить пустой конструктор.

4 голосов
/ 19 февраля 2012

Мы не знаем, может ли класс Report копировать, поэтому лучше использовать указатели.

Report * header;

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

// after all don't forget
delete header;

и, конечно, вы должны использовать указатель header вот так

header->print_formatted();
2 голосов
/ 19 февраля 2012

Самое простое, что приходит на ум, - это выполнить небольшой рефакторинг потока кода.Создайте функцию, которая обрабатывает ввод и возвращает построенный объект:

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

Затем вызывайте функцию из main.Небольшое изменение в дизайне - это введение функции, единственной обязанностью которой является создание Report из пользовательского ввода, что на самом деле имеет смысл как функция.

0 голосов
/ 06 марта 2019

Вы можете использовать ссылку rvalue для привязки на месте к любому построенному объекту.

struct Foo
{
  Foo(int bar): bar(bar) {}

  int bar
};

Foo&& f = condition ? Foo(4) : Foo(5);

f.bar = 1000; 
0 голосов
/ 19 февраля 2012

Я не уверен, правильно ли я понял ваш вопрос.Извините, если вы прочитаете ответ и поймете, что это так.

Но, тем не менее, я думаю, что основной стратегией было бы использование перегрузки конструктора.т.е. вы определяете конструкторы для обоих: случая, когда параметры не передаются, и случая, когда параметры передаются.Первый (то, что вы называете конструктором по умолчанию) инициализирует компанию и сообщает имена по умолчанию.Последний назначит полученные параметры именам компаний и отчетов.

Что касается использования указателей: этого можно избежать, «объявляя» множество объектов типа «Отчет» (класс).Например, вы можете создать массив заголовков (объектов).И тогда вы можете «определить» его как и когда пользователь ответит.

Но используя указатели, вы делаете все во время выполнения (динамическое назначение), тогда как при использовании массивов (или объявляющих много объектов): суммафиксированный.Это может быть неэффективно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...