c++ - 在不调用默认构造函数的情况下声明对象

标签 c++ object default-constructor

我是 C++ 的新手,习惯于使用 Java。 在 Java 中,我可以选择在不实例化的情况下声明一个对象,并且希望在 C++ 中做同样的事情。

假设有一些类 Foo,在 Java 中我可以编写 Foo bar; 来声明 Foo 的实例而不初始化 。 但是,在 C++ 中,当我编写 Foo bar; 时,bar 是通过调用类 Foo 的默认构造函数来初始化的。

如果我为类 Foo 编写了一个或多个构造函数,并且每个构造函数至少有一个参数,这尤其令人烦恼。在这种情况下,代码将无法编译并出现类似于 no matching function for call to 'Foo::Foo()'

的错误

例如,假设我在 Java 中有以下类定义:

public class Foo {
    private boolean b;

    Foo(boolean b) { this.b = b; }
}

以及C++中相应的类定义:

class Foo {
        bool b_;
    public:
        Foo(bool b) : b_(b) {}
};

在Java中,我可以写一些方法

public static Foo makeFoo(int x) {
    Foo result;
    if (x > 10) { result = new Foo(true); }
    else { result = new Foo(false); }
    return result;
}

但是,如果我用 C++ 编写类似的方法,则会出现编译错误:

Foo makeFoo(int x) {
    Foo result; // here, a call is made to Foo::Foo() which doesn't exist, and thus compilation fails
    if (x > 10) { 
        result = Foo(true); // this would probably also fail since I didn't specify a copy-constructor, but I'm not entirely sure
    }
    else {
        result = Foo(false); // as above, I think this would probably fail
    }
    return result;
}

虽然我给出的例子没有用,但我在编写 Java 代码时经常使用这种方法。 有没有办法在 C++ 中模拟这种行为? 或者,这只是糟糕的设计吗?如果是这样,您会推荐哪种方法?

最佳答案

如果您不想像 Igor(和其他人)在对您的问题的第一条评论中所解释的那样使用指针来获取引用功能,那么您可以做几件事。

首先,值类型而不是引用类型的理念是在需要它们之前不要创建它们。您试图在使用对象之前声明引用以在函数的其余部分(可能是一些创建后的公共(public)初始化代码)中获得某种多态功能是合理的设计,但不能以您编写它的方式表达,因为它将涉及创造值(value)。

您可以提供一个默认构造函数并赋予它一些行为——但很明显,您和其他任何人都不想被迫这样做。

替代方案的本质是将变量移动到作用域内并返回它。

Foo makeFoo(int x) {
    if (x > 10) { 
        Foo result = Foo(true);
        return result;
    }
    else {
        Foo result = Foo(false);
        return result;
    }
}

显然,这会阻止您在 return 之前的 if block 之后编写通用的创建后初始化代码。为此,您可以在自己的函数中编写 if block 并让它返回结果,然后在初始化对象后编写后续代码。

Foo premakeFoo(int x) {
    if (x > 10) { 
        Foo result = Foo(true);
        return result;
    }
    else {
        Foo result = Foo(false);
        return result;
    }
}

Foo makeFoo(int x) {
    Foo result = premakeFoo(x);
    // common post init code can go here.
    return result;
}

如果您不想在一个完全独立的函数中使用它,您可以使用 lambda。

Foo makeFoo(int x) {
    Foo result = ([=]() {
        if (x > 10) {
            Foo result = Foo(true);
            return result;
        } else {
            Foo result = Foo(false);
            return result;
        }
    })();
    // common post init code can go here.
    return result;
}

或者在您的情况下,如果它很小,请使用内联的三元表达式。

Foo makeFoo(int x) {
    Foo result = (x > 10) ? Foo(true) : Foo(false); // or just Foo(x>10)
    // common post init code can go here.
    return result;
}

还有其他涉及模板的巧妙选项,但它们都围绕着为重载构造函数隔离不同表达式,然后使用赋值来初始化给定一些更复杂表达式的变量的想法。而您要做的是获取以两种不同方式构造值的表达式,以跨越范围 block (跨越if block )。三元和函数是此处的选项,用于在单个表达式中执行 if 逻辑。

关于c++ - 在不调用默认构造函数的情况下声明对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56705602/

相关文章:

c++ - 如何用类对象填充数组结构?

javascript - 如何在 JavaScript 中将对象属性设置为 null 和空白数组?

javascript - 如何更改对象属性的值

Java:实例化一个没有默认构造函数的泛型类

c++ - "explicit"关键字对默认构造函数有影响吗?

c++ - 析构函数单元测试会被优化掉吗?

c++ - 这行三元运算符的语法是什么

c++ - 停止右值调用移动赋值 C++ 11

函数中的 JavaScript 原型(prototype)委托(delegate)

c++ - 虚拟继承中最基类是否需要默认ctor?