c++ - 声明对象而不调用默认构造函数
问题描述
我是 C++ 新手,习惯于使用 Java。在 Java 中,我可以选择声明一个对象而不实例化它,并且希望在 C++ 中做同样的事情。
假设有一些类Foo
,在 Java 中我可以编写来声明一个没有初始化Foo bar;
的实例。但是,在我编写的 C++ 中,是通过调用 class 的默认构造函数来初始化的。Foo
bar
Foo bar;
bar
Foo
如果我为 class 编写了一个或多个构造函数,这尤其令人烦恼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(和其他人)在对您的问题的第一条评论中解释的那样使用指针来获取参考功能,那么您可以做几件事。
首先,值类型而不是引用类型的理念是在您需要它们之前不要创建它们。您在使用对象之前声明引用以在函数的其余部分(可能是一些创建后的公共初始化代码)中获得某种多态功能的诱惑是合理的设计,但不能以您编写它的方式表达,因为它将涉及创造价值。
您可以提供一个默认构造函数并赋予它一些行为——但很明显,您和其他任何人都不想被迫这样做。
替代方案的本质是将变量移动到范围内并返回。
Foo makeFoo(int x) {
if (x > 10) {
Foo result = Foo(true);
return result;
}
else {
Foo result = Foo(false);
return result;
}
}
显然,这会阻止您在return之前的if块之后编写常见的创建后初始化代码。为此,您可以在自己的函数中编写if块并让它返回结果,然后在初始化对象后编写后续代码。
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;
}
还有其他一些涉及模板的巧妙选项,但它们都围绕着为重载的构造函数隔离不同的表达式,然后使用赋值来初始化一个给定一些更复杂表达式的变量的想法。您要做的是以两种不同的方式获取构造值的表达式以跨越范围块(跨越if块)。三元组和函数是此处用于在单个表达式中执行if逻辑的选项。
推荐阅读
- html - 如何为行标题和列标题创建单元格
- python - CKAN:从基本控制器继承时视图为空
- regex - 带有两位小数或非负整数的非负数的正则表达式。无前导 0
- python - 如何使用 setup.py 安装 python 程序
- node.js - 导入 redux 时出错:
- javascript - document.addEventListener 'copy' 在 IE 上不起作用
- linux - 如何使用编号菜单获得 Linux 自动完成功能?
- nginx - pouchdb 不会在 nginx 服务器上同步创建远程数据库,导致 GET 和 POST 出现大量 404
- java - Java - 重新绘制jframe时如何以编程方式模拟StdIn
- javascript - 选择具有相似类名但没有 div id 的 div