views:

41

answers:

4
class A{
};

class B{
public:
    B();
    B(const &A);
};

void foo(A &a){

}

int main(){
   B b;
   foo(b); //error: invalid initialization of reference of type ‘A&’ from expression of type ‘B’
   return 0;
}

In the above code, I have a compilation error

error: invalid initialization of reference of type ‘A&’ from expression of type ‘B’

The error can be solved by function overloading of foo(). However,do you have any other suggestion how I can solve the problem?

function foo(A &a) does not use parameter "a" as input. parameter "a" is simply the output of the function foo(A &a).

thanks.

A: 

The problem is that you are trying to implicitly convert an object B to an object A. Considering that these are to separate classes, the compiler won't be able to do this. Whilst it is possible to explicitly cast a pointer or reference to object B to a */& of object A, this would confuse the compiler and is a really bad idea.

It is like you are asking the compiler to convert an apple to an orange, can't be done. If B was a subclass of A, this would be totally possible. But you cannot simply do this as a work around if the two classes have nothing or little in common. If they do however, and you have several related classes, create a base class (that contains shared methods), and make all these classes derive from it.

And again, please don't do something like (A*)(&b) because this will lead to run-time issues if you don't know what class you are actually getting in foo()'s parameter (again, unless B derives from A).

Of course, the best course of action is to overload Foo().

EDIT: You see, you can convert from A to B in B's constructor. But you need an A and have a B, so the REVERSE conversion is needed. This is why your current code will not work.

Alexander Rafferty
iampat
+3  A: 

There are many options... hard to know what to recommend without understanding what you're program is attempting. The little insight we're given into the logical relationship between A and B is:

  • only one of B's constructor's requires a non-const reference to an A object
  • foo() is intended to work with either A or B

this implies a pointer to A may be being saved in B, but begs the question: should foo() work with all B's (perhaps using a default-constructed A if none was provided at construction) or only those that were constructed with reference to an A?

Design options include:

  • derive B from A (but your default constructor suggests a B can exist without having been "tied" to an A)
  • add A& get_A() and/or const A& get_A() const member(s) to class B, then call foo(b.get_A());
    • do this implicitly with operator A&() and operator const A&() const
    • you may prefer A* get_A() et al if A is optional
  • template <class A_or_B> foo(A_or_B&) if A and B provide the right members/semantics for foo to work on either
  • overload foo, providing different implementations for each type

Exploratory code:

#include <iostream>

struct A
{
    int n_;
};

void foo(A& a)
{
   a.n_++;
}


struct B
{
    // e.g. B() : p_a_(new A), owner_(true) { } ?
    //      ~B() { if (owner_) delete p_a_; }
    B(A& a) : p_a_(&a) { }

    operator A&() { return *p_a_; }

    A* p_a_;
};

int main()
{
    A a;
    a.n_ = 2;
    B b(a);
    foo(a);
    foo(b);
    std::cout << a.n_ << '\n';
}
Tony
Note that the implicit conversion will only work if the function/method takes an object or a const-reference as parameter.
Space_C0wb0y
iampat
Tony
@iampat: In that case your only alternatives are inheritance and overloading. Or consider not using output-parameters, but return values instead.
Space_C0wb0y
@iampat: You are right. It's too early, I should stop posting right now and drink another coffee first...
Space_C0wb0y
A: 

Do you really want A and B as unrelated classes? If A and B class share is-a relationship then better you derive B from A.

class B : public A

then also foo(b) with foo(A& a) as signature will result into object slicing.

aJ
A: 

Simplest way.. if you are willing to assign the object B in the object A. You need to see the relationship whether they compatable or not.

To make compile from my perpective try below:

class A{ 

}; 

class B: public A{ 
public: 
    B(){
    }
    B(const A&){
    }
}; 

void foo(A &a){ 

}

Hope it worths.

Santosh kumar