Reputation: 4948
This title has been used many times but after searching around 5-6 examples, I couldn't find anything that matches my problem:
I have a simple inheritance practice.
Class A is a base class, classes B & C inherit from it:
class A {
};
class B : public A { public: int i; };
class C : public A { public: int j; };
And a class P containing overloaded functions like this:
class P
{
public:
void change(B *b)
{
b->i =1;
}
void change(C *c)
{
c->j =1;
}
};
And when I use the functions like the following:
int main()
{
A *b = new B();
A *c = new C();
P p;
p.change(b);
p.change(c);
return 0;
}
it gives an error saying:
inherit2.cpp: In function ‘int main()’:
inherit2.cpp:37:12: error: call of overloaded ‘change(A*&)’ is ambiguous
inherit2.cpp:37:12: note: candidates are:
inherit2.cpp:21:7: note: void P::change(B*) <near match>
inherit2.cpp:21:7: note: no known conversion for argument 1 from ‘A*’ to ‘B*’
inherit2.cpp:26:7: note: void P::change(C*) <near match>
inherit2.cpp:26:7: note: no known conversion for argument 1 from ‘A*’ to ‘C*’
inherit2.cpp:38:12: error: call of overloaded ‘change(A*&)’ is ambiguous
inherit2.cpp:38:12: note: candidates are:
inherit2.cpp:21:7: note: void P::change(B*) <near match>
inherit2.cpp:21:7: note: no known conversion for argument 1 from ‘A*’ to ‘B*’
inherit2.cpp:26:7: note: void P::change(C*) <near match>
inherit2.cpp:26:7: note: no known conversion for argument 1 from ‘A*’ to ‘C*’
I will appreciate if you please help me solve the problem. rahman
Upvotes: 0
Views: 1330
Reputation: 29966
You could:
Use polymorphism by adding a virtual setter function for i
and j
:
class A {
public:
virtual void set( int ) = 0;
};
class B : public A {
public:
void set( int value )
{
i = value;
}
private:
int i;
};
class C : public A {
public:
void set( int value )
{
j = value;
}
private:
int j;
};
class P
{
public:
void change(A * obj)
{
obj->set(1);
}
};
int main()
{
A *b = new B();
A *c = new C();
P p;
p.change(b);
p.change(c);
return 0;
}
Case the pointer before passing it:
A *b = new B();
A *c = new C();
P p;
p.change(static_cast<B*>(b));
p.change(static_cast<C*>(c));
Place the variable into the base class (and get rid of two change()
functions):
class A {
public:
int i;
};
class B : public A {};
class C : public A {};
Upvotes: 2
Reputation: 206508
Root Cause:
When you call change()
the parameter you pass is of the type A *
, there is no exact match for this function in class P
. The compiler tries to find the best possible match and it has two choices:
void change(B *);
void change(C *);
None of them is a best match because each requires conversion from A*
to B*
or C*
. Not that your classes do not provide for this conversion function and hence compiler reports the error.
Resolution:
You tell the compiler exactly which version of the function to chose by using casting.
p.change(static_cast<B*>(b));
p.change(static_cast<C*>(c));
In both of above cases you know the actual type of the object being pointed by A *
and so you can use static_cast
and guide the compiler to find the best match function.
Upvotes: 1
Reputation: 8027
Polymorphism is one answer
class A
{
public:
virtual void set() = 0;
};
class B : public A
{
public:
virtual void set() { i = 1; }
private:
int i;
};
class C : public A
{
public:
virtual void set() { j = 1; }
private:
int j;
};
class P
{
public:
void change(A *a)
{
a->set();
}
};
int main()
{
A *b = new B();
A *c = new C();
P p;
p.change(b);
p.change(c);
return 0;
}
With polymorphism there is no need for multiple change
methods.
Upvotes: 2
Reputation: 73605
I would tweak your class hierachy to use polymorphism:
class A
{
public:
virtual void SetVariable(const int value) = 0;
};
class B : public A
{
public:
virtual void SetVariable(const int value) override { i = value; }
int i;
};
class C : public A
{
public:
virtual void SetVariable(const int value) override { j = value; }
int j;
};
class P
{
public:
void change(A *a)
{
a->SetVariable(1);
}
};
This way you can use pointers to the base class (A
) without knowing which specific derived type they are.
Upvotes: 1