Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/150.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 类类型转换失败C++;_C++_Type Conversion_Incomplete Type - Fatal编程技术网

C++ 类类型转换失败C++;

C++ 类类型转换失败C++;,c++,type-conversion,incomplete-type,C++,Type Conversion,Incomplete Type,我正在尝试编译一些东西,但它不会,而且我在网上找不到任何相关的东西 #include<iostream> using namespace std; class A; class B { int x; public: B(int i=107) {x=i;} operator A(); }; B::operator A() {return x;} class A { int x; public: A(int i=6) {x=i;} in

我正在尝试编译一些东西,但它不会,而且我在网上找不到任何相关的东西

#include<iostream>
using namespace std;

class A;
class B
{
    int x;
public:
    B(int i=107) {x=i;}
    operator A();
};
B::operator A() {return x;}

class A
{
    int x;
public:
    A(int i=6) {x=i;}
    int get_x() {return x;}
};

int main()
{
    A a;
    B b=a;
    cout<<a.get_x();
    return 0;
}
我不知道我做错了什么,我也不知道在哪里可以找到更多关于这个主题的信息


谢谢

您可以轻松地将B类声明移到A类声明下方

class A
{
    ...
};

class B
{
    ...
    operator A();
};
B::operator A() {return x;}
不要使用转发声明。然后像这样使用运算符,因为您不是将A转换为B,而是将B转换为A

B b;
A a = b; // A a = (A)b;
...

关于所发生的事情,我添加了一些打印以显示代码经过的地方

A(int i=6) {
    std::cout<<"Created A"<<std::endl;x=i;
}
A( const A& a ) {
    std::cout<<"Created A by Copy"<<std::endl;
    this->x = a.x;
}
B::operator A() {
    std::cout << "Operator A" << std::endl;
    return x;
}
因此运算符A返回一个int,用于构造A的实例,然后用于通过复制初始化实例“A”。我从来不知道你可以做这样的事情(你可能无论如何都不想做,但是是的……)


编辑:您实际上应该创建显式in运算符A()的实例,而不是依赖编译器。

您没有发布错误的全文,这意味着您遗漏了所有重要的行号。通常情况下,行号通常是错误中最有价值的信息

class A;
class B
{
    ...
};
B::operator A() {return x;}
我猜这是你的编译器告诉你错误发生的那一行

在这一行代码中,编译器还没有完整的
a
声明,因此它不知道如何将
int x
转换为
class a
。C++编译是单程,所以不能推迟这个查找。

在继续定义之前,需要完成声明

class A;
class B
{
    int x;
public:
    B(int i=107) {x=i;}
    operator A();
};

class A
{
    int x;
public:
    A(int i=6) {x=i;}
    int get_x() {return x;}
};

// done with declarations. begin definitions.

B::operator A() {return x;}
// compiler quietly expands this to be:
// B::operator A() { return A::A(i=this->x); }

通常
A
B
将位于头文件中,并且您将保留.cpp文件的定义,该定义要求两个类都被完全声明。

代码有几个问题(请参见注释)

#包括
//旁注:永远不要在标题中这样做(我也避免在源代码中这样做)
使用名称空间std;
甲级;
B类
{
int x;
公众:
B(inti=107){x=i;}
运算符A()常量;
//移动以使“主要”合理化
int get_x(){return x;}
};
甲级
{
int x;
公众:
A(inti=6){x=i;}
//使所需的转换工作:
运算符B()常量{return x;}
};
//这需要一个完整的a。换句话说,a的增量必须是未知的。
运算符A()常量{return x;}
int main()
{
A A;
B=a;

无法移动行
B::operator A(){return x;
}在
类A
之后。这就是“类A”的本质是不完整的谢谢。但是为什么类A的正向声明不起作用,我想知道?如果不先重载
=
操作符,就不能使用
=
将对象从类B转换为类A。@ILeanprofeanu在类B、B上面有正向声明ut下面的实际定义,因此类B甚至不知道什么是类A。转发声明通常在头文件中使用。如果将类B移动到类A下面,则不需要转发声明。@在这种情况下,将调用复制构造函数,因此即使不重载它,也可以使用“=”
Begin
Operator A
Created A
Created A by copy
End
class A;
class B
{
    ...
};
B::operator A() {return x;}
class A;
class B
{
    int x;
public:
    B(int i=107) {x=i;}
    operator A();
};

class A
{
    int x;
public:
    A(int i=6) {x=i;}
    int get_x() {return x;}
};

// done with declarations. begin definitions.

B::operator A() {return x;}
// compiler quietly expands this to be:
// B::operator A() { return A::A(i=this->x); }
#include<iostream>

// Side Note: Never do this in a header (I avoid it in sources, too)
using namespace std;

class A;
class B
{
    int x;
public:
    B(int i=107) {x=i;}
    operator A() const;
    // Moved to make 'main' reasonable
    int get_x() {return x;}
};

class A
{
    int x;
public:
    A(int i=6) {x=i;}
    // Make the desired conversion work:
    operator B () const { return x; }
};

// This nedds a complete A. In other words, the delaration of A has to be knonwn.
B::operator A() const {return x;}


int main()
{
    A a;
    B b=a;
    cout << b.get_x() << '\n';
    return 0;
}