Type conversion for function parameters
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 ov开发者_如何转开发erloading 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.
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/orconst A& get_A() const
member(s) toclass B
, then callfoo(b.get_A());
- do this implicitly with
operator A&()
andoperator const A&() const
- you may prefer
A* get_A()
et al if A is optional
- do this implicitly with
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';
}
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.
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.
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.
精彩评论