如果临时传递给构造函数,则对象“不是结构或联合”

时间:2016-12-01 07:42:34

标签: c++

我之前没有看到过这种奇怪的C ++,这让我有点混乱。

我有以下课程:

class KeyValuesParser
{
public:
    explicit KeyValuesParser(const QByteArray &input);
    QJsonDocument toJsonDocument(QString* errorString = nullptr);

    // ...
};

我正试图在Qt单元测试中使用它:

const char* testData = "...";
KeyValuesParser parser(QByteArray(testData));
QJsonDocument doc = parser.toJsonDocument();

这会产生以下编译错误:

Member reference base type 'KeyValuesParser(QByteArray)' is not a structure or union.

但是,如果我在堆栈上创建字节数组然后将其传入,而不是传递一个临时的,那么一切都编译好了:

const char* testData = "...";
QByteArray testByteArray(testData)
KeyValuesParser parser(testByteArray);
QJsonDocument doc = parser.toJsonDocument();

我认为这可能是一些奇怪的黑魔法需要explicit关键字(这就是我添加它的原因),但这没有任何区别。谁能解释一下这里发生了什么?

编辑:我被称为另一个问题,因为它是重复的,我认为它几乎是,但在这个问题上有一些最令人烦恼的解析混淆,我认为值得进一步讨论。

3 个答案:

答案 0 :(得分:1)

NB。这是Jonas在我附近回答的补充。

你想要做的是将rvalue绑定到左值引用,这在C ++标准中是不允许的。在你的第二个例子中 - 你正确地通过引用传递左值,这就是它工作的原因。

将rvalue绑定到左值引用是Visual C ++扩展,g ++根本不能这样做,clang可以用-fms-extensions

来做

答案 1 :(得分:0)

该行

KeyValuesParser parser(QByteArray(testData));

不是对象声明。它是函数的函数声明,返回KeyValuesParser并获取QByteArray参数。

这称为Most Vexing Parse(链接转到维基百科,你也可以在StackOverflow上找到很多)。为了简短起见,如果有疑问,C ++标准更喜欢函数声明,因为otherwise it would be hard to declare functions at all

答案 2 :(得分:0)

如上所述,这是一个最令人烦恼的解析"问题。 c ++ 11为我们带来了两个解决方案:auto和括号初始化:

// use auto to turn the expression unambiguously into an rvalue
// without having to mention the class name twice
int main()
{
  const char* testData = "...";
  auto parser = KeyValuesParser(QByteArray(testData));
  auto doc = QJsonDocument(parser.toJsonDocument());
}


// or use brace initialisation to avoid the parse ambiguity 
//    
int main2()
{
  const char* testData = "...";
  KeyValuesParser parser{ QByteArray(testData) };
  QJsonDocument doc{ parser.toJsonDocument() };
}

// another solution:

const char* testData = "...";
auto doc = QJsonDocument(KeyValuesParser(QByteArray(testData)).toJsonDocument());

// yet another

const char* testData = "...";
auto doc = QJsonDocument { KeyValuesParser { QByteArray(testData) }.toJsonDocument() };