#include<iostream>
using namespace std;
class ParentClass {
public:
virtual void someFunc(int a){
printf(" ParentClass :: someFunc (int) \n");
};
virtual void someFunc(int* a){
printf(" ParentClass :: someFunc (int*) \n");
};
};
class ChildClass : public ParentClass {
public:
virtual void someFunc(int* a){
printf(" ChildClass :: someFunc(int*) \n");
};
};
int main(){
ChildClass obj;
/* This function call results in an error: */
obj.someFunc(7);
}
Первый дает ошибку как
tr2.cpp: In function 'int main()':
tr2.cpp:27:19: error: invalid conversion from 'int' to 'int*' [-fpermissive]
obj.someFunc(7);
^
tr2.cpp:18:18: error: initializing argument 1 of 'virtual void ChildClass::som
eFunc(int*)' [-fpermissive]
virtual void someFunc(int* a){
^
Но если мы изменим метод для принятия char вместо int *, тогда
#include<iostream>
using namespace std;
class ParentClass {
public:
virtual void someFunc(int a){
printf(" ParentClass :: someFunc (int) \n");
};
virtual void someFunc(char a){
printf(" ParentClass :: someFunc (char) \n");
};
};
class ChildClass : public ParentClass {
public:
virtual void someFunc(char a){
cout<<a<<endl;
printf(" ChildClass :: someFunc(char) \n");
};
};
int main(){
ChildClass obj;
/* This function call results in an error: */
obj.someFunc(7);
}
выход:
ChildClass :: someFunc(char)
Со звуком Windows (динь). — ANS: неявное преобразование здесь. Пожалуйста, проверьте редактирование ниже.
Таким образом, скрытие имени работает в первом примере, но не во втором. кто-нибудь может объяснить почему? Я также попытался создать перегруженную переопределенную виртуальную функцию с различным количеством параметров, таких как
int func (int a), int func (int a, int b), а затем переопределяют только один из них. В этом случае также не работает скрытие имен, производный класс может получить виртуальную функцию базового класса, которая не переопределяется.
Почему это имя скрывает работу только в этом конкретном случае?
РЕДАКТИРОВАТЬ 1:
With Context to Eternals Объяснение неявного преобразования. У меня есть другая программа, которая должна быть скрыта от имени, но нет. В этой версии методы дифференцируются на основе разных аргументов.
#include<iostream>
using namespace std;
class ABC
{ public:
ABC()
{
cout<<"Constructor ABC"<<endl;
}
virtual void meth1(int a);
virtual void meth2(int a, int b);
};
void ABC :: meth1(int a)
{
cout<<"One"<<endl;
}
void ABC:: meth2(int a, int b)
{
cout<<"Two"<<endl;
}
class BC:public ABC
{
public:
BC()
{
cout<<"Cons B"<<endl;
}
void meth1(int a);
};
void BC :: meth1(int a)
{
cout<<"Three"<<endl;
}
int main()
{
BC b;
b.meth1(5);
b.meth2(6,7);
}
выход:
C:\Users\Shaurya\Desktop>a
Constructor ABC
Cons B
Three
Two
Скрытие имени в этом случае также не работает.
Когда вы перегружены someFunc()
в ChildClass
это скрывает две перегрузки от ParentClass
, В первом случае вы вызываете функцию, которая принимает int*
как аргумент с целым числом, так что, конечно, он падает, потому что не может выполнить преобразование.
Во втором случае вы вызываете функцию, которая принимает char
как аргумент с целым числом, так что есть неявное преобразование, и все в порядке.
Обновление после РЕДАКТИРОВАНИЯ 1:
Я не понимаю, чего вы ожидали:
BC
, который является ребенком от ABC
так что есть вызов ABC
конструктор тогда BC
«smeth1()
: поскольку BC
переопределяет это, BC::meth1()
называетсяmeth2()
: поскольку BC
не отменяет это, ABC::meth2()
называетсяЕдинственное «сокрытие имени», которое здесь происходит, это переопределение meth1 BC, но на самом деле это ничего не скрывает …
В вашем «РЕДАКТИРОВАТЬ 1» имя не скрывается. b.meth2(6,7)
не могу найти meth2
в BC
так это выглядит в ABC
, Но если вы переименуете meth2
в meth1
везде в программе она не будет компилироваться из-за сокрытия имени: BC::meth1(int)
скроет ABC::meth1(int, int)
,
РЕДАКТИРОВАТЬ: краткое объяснение того, как работает поиск членов класса. Когда компилятор видит object.method(args)
, где статический тип из object
является class C
сначала он ищет функцию-член member
в декларации class C
, Если он найдет его (или несколько перегрузок), он перестает искать member
где-нибудь еще. Если нет, то это выглядит в C
базовые классы, следуя некоторым загадочным правилам, полностью описанным в стандартной части C ++ 10.2 Member name lookup
,
Как только кандидаты найдены, компилятор проверяет, может ли любой из кандидатов быть вызван с заданными аргументами. Если да, и это можно сделать однозначно, функция найдена. В противном случае программа является плохо сформированной. Этот процесс называется разрешение перегрузки и описано частично 13.3
стандарта.
Обратите внимание, что нет слова virtual
в приведенном выше объяснении.