Implicit Conversion - c++

My program was:-
#include < iostream.h>
#include < conio.h>
struct base
{
protected:
void get()
{
cin>>a>>b;
}
public:
base(int i=0, int j=0);
void put()
{
cout << a << '\t' << b << "\tput 1";
}
int a,b,c;
~base()
{
cout << "base destroyed";
}
};
class deri : protected base
{
int c,d;
char w;
int ans;
public:
deri(int r=7, int s=0)
: base(r,s)
{
c=r;
d=s;
cout << "\nDerived invoked\n";
}
void put()
{
cout << c << '\t' << d << '\t' << a << '\t' << b;
}
};
class d2 : protected deri
{
public:
d2() {}
void start();
void add()
{
get(); // ERROR HERE: Implicit conversion of 'd2 *' to 'base *' not allowed
}
~d2(){}
};
void d2::start()
{
put();
}
base::base(int i, int j)
{
a=i;
b=j;
cout << "\nbase invoked\n";
cout << "Enter a,b: ";
get();
}
void main()
{
clrscr();
getch();
}
CAN anyone explain what the error msg means?

You are probably using an old compiler as you're including <iostream.h> instead of the new standard <iostream> and you aren't using namespace std.
After fixing this, adding the line using namespace std; on top and commenting out clrscr() your code compiles fine on MSVC8.
Do you have a clear reason to use protected derviation ? If not, I'd suggest using public derviation instead. protected derviation is something really quite complicated and uncommon.

When you derive a base class using protected or private then your derived class is not treated as base class and compiler will not perform implicit type conversion in that case.
Derived class in not base class in case of private or protected inheritance.
whereas in case of public inheritance every derived class is a base class .
Try out explicit type casting in the function or make inheritance public.

Related

Overloading a virtual function

I am trying to overload a virtual function, like this:
#include<iostream>
#include<string>
using std::cout;
using std::endl;
using std::string;
class Base{
public:
virtual void show(int x){
cout << "Showing int as Base: " << x << endl;
}
};
class Derived : public Base{
public:
using Base::show;
virtual void show(string s){
cout << "Showing string as Derived: " << s << endl;
}
};
int main(){
Derived x;
Base& ref = x;
ref.show(3);
ref.show(string("hi")/*in case the compiler refuses to implicitly convert const char* to std::string*/);
}
However, GCC complains error: cannot convert 'std::string' {aka 'std::__cxx11::basic_string<char>'} to 'int', and says note: initializing argument 1 of 'virtual void Base::show(int)'
It seems like gcc just ignored the Derived's overload of show.
I suspect that overloading together with polymorphism is just a BIT too much to handle for the compiler, since that would require storing the type information in the vtable as well, which MAY be not possible.
But then, what should I do to mimic this behaviour?
This worked:
#include<iostream>
#include<string>
#include<any>
using std::cout;
using std::endl;
using std::string;
using std::any;
using std::any_cast;
class Base{
public:
virtual void show(int x){
cout << "Showing int as Base: " << x << endl;
}
virtual void show(any x) = 0;
};
class Derived : public Base{
public:
using Base::show;
virtual void show(any s) override{
if(s.type() != typeid(std::string)){
if(s.type() != typeid(int)){
throw "SOME_ERROR_INDICATING_INVALID_FUNCTION_CALL";
}
Base::show(any_cast<int>(s));
return;
}
cout << "Showing string as Derived: " << any_cast<string>(s) << endl;
}
};
int main(){
Derived x;
Base& ref = x;
ref.show(3);
ref.show(string("hi")/*invokes show(any) override */);
}
but it seems really stupid. Is there any other workaround?
EDIT: adding virtual void show(string x)=0; to base is NOT desireable. This is just a MRE, and in the real program I have lots of derived classes, and I don't want to add a pure virtual function in Base for each of those customizations.
The problem is that you're calling show through a reference to a base object while passing a std::string as an argument but the base class doesn't have any such method so this call can't succeed.
To solve this you can add a declaration for virtual void show(string s) =0; inside the base class.
class Base{
public:
virtual void show(int x){
cout << "Showing int as Base: " << x << endl;
}
//added this declaration for making it pure virtual
virtual void show(string s)=0;
};

How to deal with base class and pointer variable in argument

I am trying to deal with abstract class argument, trying to figure out what to do, after running this code below getting the error : "In function 'int main()': 67:12: error: expected primary-expression before ')' token"
#include <iostream>
#include <string>
using namespace std;
class base1 {
protected:
int i;
public:
base1(int x) {
i=x;
cout << "Constructing base1\n";
}
virtual ~base1() {
cout << "Destructing base1\n";
}
};
class derived: public base1 {
int j;
public:
derived(int x, int y): base1(y){
j=x;
cout << "Constructing derived\n";
}
~derived() {
cout << "Destructing derived\n";
}
void show() {
cout << i << " " << j << " " << "\n";
}
};
class Isolver
{
public :
Isolver(){};
virtual ~ Isolver(){};
virtual void x(base1* pboard)=0;
};
class vr:public Isolver
{
void x(base1* pboard)
{
cout << "My virtual fun and base constructor are not working\n"<<endl;
};
};
int main()
{
vr obj;
obj. x(10, );
derived ob(3,4);
ob.show();
return 0;
}
Like Paul Rooney pointed out the comma inside obj.x(10,) should not be there because with the comma the compiler is expecting two arguments and since there is nothing after the comma it shows an error.
This is what you need to do inside main:
vr obj;
base1 b(1);
obj. x(&b);
or this:
vr obj;
derived ob(3,4);
obj. x(&ob);
ob.show();
and inside class vr
class vr:public Isolver
{
public:
void x(base1* pboard)
{
cout << "My virtual fun and base constructor are not working\n"<<endl;
}
};

C++ polymorphism, about announcing a basis class reference to a derived class

#include <iostream>
using namespace std;
class A {
private:
int nVal;
public:
void Fun()
{
cout << "A::Fun" << endl;
}
void Do()
{
cout << "A::Do" << endl;
}
};
class B :public A {
public:
virtual void Do()
{
cout << "B::Do" << endl;
}
};
class C :public B {
public:
void Do()
{
cout << "C::Do" << endl;
}
void Fun()
{
cout << "C::Fun" << endl;
}
};
void Call(B& p)
{
p.Fun(); p.Do();
}
int main() {
C c; Call(c);
return 0;
}
In the above code, the output is
A::Fun
C::Do
But I cannot understand. in the function call(B& p), the reference p should refer to c from C class, so why the output is not
C::Fun
C::Do
When announcing a a basis class reference to a derived class, is the different basis class making any sense?
The problem is that A::Fun is not marked as virtual, therefore it doesn't find C::Fun at run-time. You should mark it as such:
class A {
private:
int nVal;
public:
virtual void Fun()
{
cout << "A::Fun" << endl;
}
// ...
wandbox example
This is a great example of an error that could be caught at compile-time thanks to the override specifier:
class C :public B {
public:
void Do() override
{
cout << "C::Do" << endl;
}
void Fun() override
{
cout << "C::Fun" << endl;
}
};
Would print:
error: 'void C::Fun()' marked 'override', but does not override
void Fun() override
^~~
wandbox example

C++ overloading method based on derived class

I am facing the following problem with my code:
#include <iostream>
using namespace std;
class Base {
public:
virtual void sayHello()=0;
};
class Impl1 : public Base {
public:
void sayHello() { cout << "Hi from Impl1" << endl; }
};
class Impl2 : public Base {
public:
void sayHello() { cout << "Hi from Impl2" << endl; }
};
void sayHello(Impl1 *i) {
cout << "Impl1 says: ";
i->sayHello();
}
void sayHello(Impl2 *i) {
cout << "Impl2 says: ";
i->sayHello();
}
int main()
{
Impl1 *i1 = new Impl1();
Base *b = i1;
sayHello(b);
return 0;
}
And here the compiler complains about the sayHello(b); line in the
code.
"call of overloaded 'sayHello(Base*&)' is ambiguous"
Is there a way to solve this problem?
EDIT:
I basically want to pass my object to a function that does some calculations based on the type of the object. My object intentionally lacks of information in order to make the needed calculations. So Impl1 and Impl2 just contain some basic data, without the knowledge of more data needed to do the calculations.
Overload resolution is performed at compile time. It means for sayHello(b);, the compiler only know that the type of b is Base*, it won't and can't know that b is pointing to a Impl1 object actually. Then results in ambiguous call; converting Base* to Impl1* or Impl2* is equivalent rank for the call.
PS: might be OT, but for you code sample, a function taking a Base* would work fine; dynamic dispach will take effect.
class Base {
public:
virtual void sayHello()=0;
};
class Impl1 : public Base {
public:
void sayHello() { cout << "Hi from Impl1" << endl; }
};
class Impl2 : public Base {
public:
void sayHello() { cout << "Hi from Impl2" << endl; }
};
void sayHello(Base *i) {
cout << "Some derived class of Base says: ";
i->sayHello();
}
int main()
{
Impl1 i1;
Impl2 i2;
Base *b = &i1;
sayHello(b); // "Hi from Impl1"
b = &i2;
sayHello(b); // "Hi from Impl2"
return 0;
}
If you need to know the dynamic type at run-time, you can use dynamic_cast. e.g.
Base *b = /* something */;
Impl1 * pi1 = dynamic_cast<Impl1*>(b);
if (pi1 != nullptr) sayHello(pi1);
Since overloads are resolved at compile time, you have to supply the compiler with the exact type in order for the overload resolution to succeed.
In order to dispatch on the type, add a virtual member function to the Base, and use it to choose the overload:
class Base {
public:
virtual void sayHello()=0;
virtual void callSayHello() = 0;
};
class Impl1 : public Base {
public:
void sayHello() { cout << "Hi from Impl1" << endl; }
void callSayHello() {sayHello(this); }
};
class Impl2 : public Base {
public:
void sayHello() { cout << "Hi from Impl2" << endl; }
void callSayHello() {sayHello(this); }
};
void sayHello(Impl1 *i) {
cout << "Impl1 says: ";
i->sayHello();
}
void sayHello(Impl2 *i) {
cout << "Impl2 says: ";
i->sayHello();
}
...
b->callSayHello();
Note that implementations of callSayHello are identical, but you cannot place them into Base class, because the type of this would be different.
Note: the idea for this implementation is borrowed from C++ implementation of the Visitor Pattern.
Get rid of the two free-standing functions and call b->sayHello(); directly:
Impl1 *i1 = new Impl1();
Base *b = i1;
b->sayHello();
Or use an ugly workaround with dynamic_cast:
Impl1 *i1 = new Impl1();
Base *b = i1;
sayHello(dynamic_cast<Impl1*>(b));
The need to resort to dynamic_cast often suggests an error in the class design. This may very well be the case here. Chances are that you should never have introduced a supposedly object-oriented base class in the first place.
Note also that you do not call delete at the end. If you do, you will need a virtual destructor in Base.

Accessing Private data types

#include <iostream>
using namespace std;
class A {
private :
typedef struct {
int a;
int j;
}type;
public :
A(){};
~A(){};
void CreateInstance();
};
class B : public A
{
private :
int d;
int n;
public :
B(){};
~B(){};
void CreateInstance1();
};
void A :: CreateInstance()
{
A::type A;
A.a = 0x10;
cout << " Val = " << A.a << endl;
}
void B :: CreateInstance1()
{
// I want to create a Pointer/instance of structure in this function. Dont want to use Public method in Class A
A::type A;
A.a = 0x10;
cout << " Val = " << A.a << endl;
}
int main()
{
A obj;
obj.CreateInstance();
B obj1;
obj1.CreateInstance1();
cin.get();
return 0;
}
I am Looking forward to have some suggestion on this .
How can i create an instance the structure "type" in derived class.
Please let me know how i can use the "data type".
Error : 'typedef struct A :: type A :: type' is Private.
Thanks in Advance.
You cannot use anything private from the base class, it is the rule of the language.
You can, however, use anything public or protected. In you case it, probably, will be sufficient to call the base class function CreateInstance
void B :: CreateInstance1()
{
A::CreateInstance();
}
(In general it is better to keep cohesive naming: if applicable, consider declaring the function CreateInstance virtual and then rename CreateInstance1 as CreateInstance to make it an overwrite of A::CreateInstance. It is not related to the question, though).
Some possibilities:
Change type to protected (but you say you can't).
Use friend class B; in A (but then you could make the type protected too, I suppose).
Ugly hack: re-declare the struct in B, creating identical type. Then use memcpy to copy between variables of the types if needed.
#include <iostream>
using namespace std;
class A {
//woh that worked .. i did mistake here
friend class B;
private :
typedef struct {
int a;
int j;
}type;
public :
A(){};
~A(){};
void CreateInstance();
};
class B : public A
{
private :
int d;
int n;
public :
B(){};
~B(){};
void CreateInstance1();
};
void A :: CreateInstance()
{
A::type A;
A.a = 0x10;
cout << " Val = " << A.a << endl;
}
void B :: CreateInstance1()
{
// I want to create a Pointer/instance of structure in this function. Dont want to use Public method in Class A
A::type A;
A.a = 0x10;
cout << " Val = " << A.a << endl;
}
int main()
{
A obj;
obj.CreateInstance();
B obj1;
obj1.CreateInstance1();
cin.get();
return 0;
}
If you need it to work so badly, you can try something in these lines
Add a static method in A which creates object instances
static A::type GetTypeInstance();
A::type A :: GetTypeInstance()
{
A::type lc_Atype;
return tp;
}
So your B::CreateInstance1 will be
void B :: CreateInstance1()
{
auto A(A::GetTypeInstance());
A.a = 0x10;
cout << " Val = " << A.a << endl;
}
Note that it creates unnecessary temporary objects if your compiler doesnt do RVO
My prev answer uses C++11. Here's another way of doing this without auto.
class A {
private :
typedef struct {
int a;
int j;
}type;
public :
A(){};
~A(){};
void CreateInstance();
typedef type AType; **//Added this typedef**
};
Change your B :: CreateInstance1 to
void B :: CreateInstance1()
{
A::AType A; **//Now this works**
A.a = 0x10;
cout << " Val = " << A.a << endl;
}
This solution works because private hides the name and not the type as such. So we can can still expose type by wrapping it using public typedef.