|
The following code gives error. Is there any explanation?
The issue is Child class is not able to use Parent class functions.
Using g++ (GCC) 3.4.6 20060404 (Red Hat 3.4.6-10)
--------------------------------
#include<iostream>
#include<string>
using namespace std;
class Parent {
public:
Parent(){}
virtual ~Parent(){}
virtual void Run()=0;
protected:
virtual void Form(string abc)=0;
protected:
virtual void Form(string abc, int i)
{
cout<<"ParentForm1 abc:"<<i<<endl;
}
};
class Child:public Parent{
public:
Child():Parent(){}
virtual ~Child(){}
virtual void Run()
{
cout<<"Child run "<<endl;
Form("ABC",1,4);
Form("DEF");
}
protected:
virtual void Form(string abc, string def)
{
cout<<"ChildForm 1 abc:"<<abc<<" Def:"<<def<<endl;
Form(def);
}
virtual void Form(string abc,int i , int b)
{
cout<<"ChildForm2 abc:"<<i<<b<<endl;
Form(abc,i);
}
virtual void Form(string abc)
{
cout<<"ChildForm3 Overridden abc:"<<endl;
}
virtual void TestForm(){
string abc("abababa");
int i=5;
//Parent::Form(abc,i);// This works
Form(abc,i);
}
};
main()
{
Child child;
child.Run();
}
---------------------------------------
$ g++ test_inherit.cpp
test_inherit.cpp: In member function `virtual void Child::Form(std::string, int, int)':
test_inherit.cpp:38: error: invalid conversion from `int' to `const char*'
test_inherit.cpp:38: error: initializing argument 1 of `std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]'
test_inherit.cpp: In member function `virtual void Child::TestForm()':
test_inherit.cpp:48: error: invalid conversion from `int' to `const char*'
test_inherit.cpp:48: error: initializing argument 1 of `std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]'
|
|
|
There is a
virtual void Form(string abc, int i);
in class Parent.
and you want to invoke the method in
virtual void Form(string abc,int i , int b);
virtual void TestForm();
in class Child.
it is a mistake.
In class Child, you give two new methods
virtual void Form(string abc, string def);
virtual void Form(string abc,int i , int b);
and override two methods of Parent
virtual void Form(string abc,int i , int b);
virtual void Form(string abc);
They hides the name Form of Parent in class Child, if you want to invoke the method in class Child, you must specify the class name. like this.
Parent::Form(abc,i);
|
|
|
|
|
Thanks for the reply. But as the arguments are different here, should not the C++ compiler resolved it by using name mangling ?
ahjo_nora
|
|
|
>>should not the C++ compiler resolved it by using name mangling ?
You mean that overloading?
First, you overrided the method -Form in class Child, it hides the Form in class Parent. So, there are just two method -
virtual void Form(string abc, string def);
virtual void Form(string abc,int i , int b);
to be candidated if you invoke the method Form in class Child.
No virtual void Form(string abc) to be candidated, because you have already hidden it.
|
|
|
Thanks jinhao for your input. So what I understand from the discussion is that:
if I override any of the function from the Parent in child, none of the other functions will be available in Child. Is it C++ standard rule?
Here Parent functions:
Form(string)=0;
Form(string, int);
Child Functions:
Form(string) // This has to be defined for parent pure virtual function
Form(string, string)
Form(string,int,int)
//Form(string,int) is not overloaded and I assumed that this is available
// in Child.
So the only way to invoke Form(string,int) in Child is to be specific, like Parent::Form(string, int).
Thanks for your thoughtful discussion.
ahjo
|
|
|
Yes, it is a standard C++ rule.
Giving a same name with a virtual function of the base class in a child class, this is called overriding. Overriding will hide the name of the base class.
Giving a same name with an existing function and different signature in a same scope, this is called overloading.
E.g.
class B
{
public:
void foo(){}
};
class A: public B
{
public:
void foo(int) //Hides the B::foo
{
foo(); //What is foo?
}
};
foo in class A is not a overloading function, because the 2 functions is not defined in a same scope. So, A::foo hides the B::foo.
Continue.
class B
{
public:
void foo(){}
};
class A: public B
{
public:
using B::foo; //using-declaration
void foo(int) //Hides the B::foo
{
foo(); //What is foo?
}
};
using-declaration can introduce a name into current scope, if current scope has not a such name, name mangling will use the name which is declared by using-declaration.
Now, class A has not defined a void foo(), and foo(int) can invoke the foo() successfully, and it refers to B::foo;
Name hidding is so normal, like this.
int i;
int main()
{
int i;
i = 5; //Which i?
}
Which i? Obviously, the i defined in main. It hides the i in global scope.
|
|
|
Thanks a lot Jinhao for the answer.
ahjo_nora
|
|
|
|
|
|
|
// |