在条件c+中创建对象+;声明 我学习C++,我刚学到了面向对象的章节。我有一个关于在if语句中创建对象的问题

在条件c+中创建对象+;声明 我学习C++,我刚学到了面向对象的章节。我有一个关于在if语句中创建对象的问题,c++,class,object,if-statement,constructor,C++,Class,Object,If Statement,Constructor,我正在处理的问题是创建一个显示报告标题的类。该类有一个默认构造函数,用于将公司名称和报告名称设置为泛型,如果用户需要,还具有一个接受两个参数(字符串company name和report name)的构造函数 问题具体地说是,“双参数默认构造函数应允许在创建新报表对象时指定这些[公司和报表名称]。如果用户创建报表对象时未传递任何参数,请使用默认值。否则,请使用用户指定的名称值。” 所以我的问题是,如何创建这些对象?我了解如何创建一个没有任何参数(即Report newobj;)的对象,以及如何创

我正在处理的问题是创建一个显示报告标题的类。该类有一个默认构造函数,用于将公司名称和报告名称设置为泛型,如果用户需要,还具有一个接受两个参数(字符串company name和report name)的构造函数

问题具体地说是,“双参数默认构造函数应允许在创建新报表对象时指定这些[公司和报表名称]。如果用户创建报表对象时未传递任何参数,请使用默认值。否则,请使用用户指定的名称值。”

所以我的问题是,如何创建这些对象?我了解如何创建一个没有任何参数(即Report newobj;)的对象,以及如何创建带有参数(即Report newobj(string);)的对象。基本上,我知道如何在我的主函数的顶部创建这些对象。但是,是否有可能根据用户的选择在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;
}
#包括
#包括
#包括“report.h”
使用名称空间std;
bool输入公司名称();//如果用户希望输入公司名称,则返回true
bool print_form();//如果用户希望在格式化输出中打印,则返回true
int main()
{
字符串公司名称,
报告单位名称;
bool name=false,
格式=假;
name=输入公司名称();
格式=打印表单();
如果(姓名)
{
不能选择;
如果(选项='y'| |选项=='y')
返回true;
其他的
返回false;
}
bool print_form()
{
字符选择;
选择;
如果(选项='y'| |选项=='y')
返回true;
其他的
返回false;
}

所以我想用默认值创建一个对象,如果没有指定,或者用一个用户值创建一个对象,如果这是给定的选择。我就是无法理解如何在C++中交互式地进行。我到目前为止还没有找到任何类似的问题。 我遇到的最接近的事情是使用指针来做一些类似于我想做的事情,但是我正在使用的书还没有找到指针,我想尝试找出一种方法来做到这一点,在我正在工作的章节的范围内(即不使用指针)

我没有包括头文件或类实现文件,因为我认为它们在这里不相关


提前谢谢!

我不知道我是否正确理解了您的问题,但您能否在if/else块之前声明报告,然后在其中初始化

Report header;

if (...) {
  header = Report();
else
  header = Report(name,company);
或者用一种较短的方式:

Report header; // calls default constructor

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

当然,这需要定义空构造函数。

我们不知道class
Report
是否可以复制,所以最好使用指针

Report * header;

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

// after all don't forget
delete header;
当然,你应该像那样使用
标题
指针

header->print_formatted();

我不确定我是否正确理解了你的问题。如果你阅读了答案并意识到事实如此,我会道歉

但是,我认为主要的策略应该是使用构造函数重载,也就是说,您为这两种情况定义构造函数:没有传递参数的情况和传递参数的情况。 前者(您称之为默认构造函数)将公司和报告名称初始化为默认值。后者将收到的参数分配给公司和报告名称

至于指针的使用:您可以通过“声明”许多类型为“Report”(class)的对象来避免它。例如,您可以创建一个header(objects)数组。 然后,当用户响应时,您可以“定义”它


但通过使用指针,您可以在运行时(动态赋值)完成所有工作,而在使用数组(或声明许多对象)时:数量是固定的。这可能是低效的。

想到的最简单的事情是对代码流执行一点重构。创建一个处理输入并返回构造对象的函数:

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

然后从main调用函数。设计中的一个小变化是引入了一个函数,该函数的唯一职责是从用户输入创建一个
报告,这实际上是一个函数。

首先,您不能在条件语句中创建一个对象并在条件语句之后使用它:two条件语句的分支创建一个作用域,每个作用域以及在分支末尾销毁的任何对象。也就是说,您需要想出一种不同的方法。最简单的方法可能是将对象的创建委托给一个函数,该函数会根据需要返回对象:

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

...
Report report = makeReport();
另一种方法是使用三元运算符以某种方式有条件地创建
报告

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();

所有这些方法都假设
报表
类实际上是可复制的。

您可以使用右值引用就地绑定到任何构造的对象

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

  int bar
};

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

f.bar = 1000; 

从C++17开始,您现在可以使用它来执行此任务-它避免了动态内存分配,避免了对象的两阶段构造,并且不要求类型是可移动或可复制的。它允许您延迟对象的构造,同时将其保留在堆栈上,并且仍然是异常安全的。如果您在每个分支中构造它您可以在事后安全地使用它,而不会造成性能损失。它还可以作为类成员使用,从而避免与右值引用解决方案不同的类构造函数初始值设定项问题。演示:

生成的程序集与with
std::optional
相同:

尽管如此,我还是建议使用现有库来补充您对
std::optional
的访问不足,而不是像我上面所做的那样滚动您自己的库-我的版本不适用于
#include <optional>

struct UseCtorA final {};
struct UseCtorB final {};
struct Report final
{
    Report() = delete;
    Report(Report const &) = delete;
    Report(Report &&) = delete;
    Report &operator=(Report const &) = delete;
    Report &operator=(Report &&) = delete;

    Report(UseCtorA, char c) : v{1} { if(c == 't'){ throw 3; } }
    Report(UseCtorB) : v{2} {}

    constexpr auto getValue() const noexcept { return v; }

private:
    int v;
};

int main(int nargs, char const *const *args)
{
    std::optional<Report> report;
    if(nargs > 2)
    {
        report.emplace(UseCtorA{}, args[1][0]);
    }
    else
    {
        report.emplace(UseCtorB{});
    }
    return report->getValue();
}
struct Empty final {};
template<typename T>
struct Optional
{
    Optional() noexcept : unused{} {}
    ~Optional() noexcept(noexcept(v.~T()))
    {
        if(constructed_successfully)
        {
            v.~T();
        }
    }
    template<typename... Args>
    auto emplace(Args &&... args) -> T &
    {
        if(constructed_successfully)
        {
            v.~T();
            constructed_successfully = false;
        }
        T &r = *new (&v) T(std::forward<Args>(args)...);
        constructed_successfully = true;
        return r;
    }
    auto operator->() noexcept -> T *
    {
        return &v;
    }

private:
    union
    {
        T v;
        [[no_unique_address]] Empty unused;
    };
    bool constructed_successfully = false;
};