class type conversion fails C++

320 views Asked by At

I'm trying to make something compile, but it won't, and I couldn't find anything relevant on the web.

#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;
}

I get the errors: return type 'class A' is incomplete conversion from 'A' to non-scalar type 'B' requested

Not even this works:

    B B;
    A a=b;

I don't know what I do wrong, and I don't know where to find more info on the subject.

Thank you

3

There are 3 answers

0
kfsone On BEST ANSWER

You didn't post the full text of your errors, which means you left out the all important line numbers. As is often the case, the line numbers are often the most valuable piece of information in an error.

class A;
class B
{
    ...
};
B::operator A() {return x;}

I'm guessing that this is the line your compiler is telling you the error occurs on.

At this line of code, the compiler does not yet have a complete declaration of A so it has no idea how to convert int x into class A. C++ compilation is single pass, so it can't defer this lookup.

You need to complete your declarations before you proceed to the definitions.

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

Typically A and B would be in header files and you would keep the definition, which requires both classes to be fully declared, for a .cpp file somewhere.

0
aslg On

You can easily move class B's declaration below class A's declaration.

class A
{
    ...
};

class B
{
    ...
    operator A();
};
B::operator A() {return x;}

And not use the forward declaration. Then use the operator like this, because you are not converting A to B, but B to A.

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

About what happens I added some prints to show where the code goes through,

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;
}

And ran this,

B b;
std::cout << "Begin" << std::endl;
A a = b;
std::cout << "End" << std::endl;
...

This is the output,

Begin
Operator A
Created A
Created A by copy
End

So operator A returns an int, which is used to construct an instance of A which is then used to initialize the instance 'a' by copy. I never knew you could do things like these (You probably don't want to do it anyway, but yeah..)

Edit: You should actually be creating an instance of A explicitly in operator A() instead of relying on the compiler.

0
AudioBubble On

The code has several issues (See the comments)

#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;
}