class base
{
public:
static void func()
{
cout<<"in base class\n";
}
};
class derived: public base
{
public:
void func()
{
cout<<"In derived class\n";
}
};
main() {
derived d;
d.func();
}
Если я сделаю функцию статической в базовом классе и создаю функцию в производном классе с тем же именем, почему эта функция переопределена, даже если она статическая?
Он не будет переопределен, в противном случае у вас будет ошибка компиляции из-за одного правила определения. У вас есть 2 функции, одна член и одна статическая. d.func()
является функцией-членом (как .
предлагает). Другая функция base::func()
, которая является статической функцией (как ::
предлагает).
Он не будет переопределен, иначе вы нарушите правило одного определения.
То, что вы видите, это «сфера»:
Если имя определено во внутренней области, оно затеняет (скрывает) все определения того же имени во внешней области.
Вы по-прежнему можете ссылаться на функцию во внешней области видимости (базовый класс) с явной квалификацией:
base::func
Чтобы добавить их из внешней области видимости в набор перегрузки, используйте using
-declaration:
using base::func;
Если ты так сделаешь, base::func
будет вызываться при использовании derived::func()
а также derived::func
будет вызываться при использовании derivedobject.func()
,
Вы испытываете «слежку». То же самое возможно с функциями-членами:
#include <iostream>
struct B {
void func() { std::cout << "in base\n"; }
};
struct D : public B {
void func() { std::cout << "in derived\n"; }
};
int main() {
D d;
d.func();
}
Это, как предположили другие, называется «затенением», одно определение скрывает другое.
Важно помнить, что вызов статической функции разрешается во время компиляции. Таким образом, следующее будет иметь ожидаемое вами поведение, но это технически неправильное поведение, потому что оно не позволяет вам вызывать самый верхний ‘func’ при использовании указателя базового класса:
void callFunc(base* b) {
b->func();
}
int main() {
derived d;
callFunc(&b);
}
потому что на сайте вызова, b->
указывает на base
и позвонил бы base::func
вместо derived::func
, Во время компиляции все, что знает компилятор, это то, что «b» base
,
Большинство людей ожидают и хотят динамичного поведения:
#include <iostream>
struct Animal {
const char* say() { return "???"; }
};
struct Fox : public Animal {
const char* say() { return "A ring ding ding"; }
};
struct Cat : public Animal {
const char* say() { return "Meow"; }
};
void whatDoesItSay(const char* name, Animal* animal) {
std::cout << "The " << name << " says " << animal->say() << ".\n";
}
int main() {
Cat cat;
Fox fox;
whatDoesItSay("cat", &cat);
whatDoesItSay("fox", &fox);
}
Это не имеет желаемого поведения:
Вместо этого нам нужно использовать ключевое слово «virtual» в базовом классе, чтобы указать, что мы хотим полностью полиморфное поведение, и мы можем использовать новое ключевое слово C ++ 11 «override», чтобы убедиться, что мы делаем это:
#include <iostream>
struct Animal {
virtual const char* say() { return "???"; }
};
struct Fox : public Animal {
const char* say() override { return "A ring ding ding"; }
};
struct Cat : public Animal {
const char* say() override { return "Meow"; }
};
void whatDoesItSay(const char* name, Animal* animal) {
std::cout << "The " << name << " says " << animal->say() << ".\n";
}
int main() {
Cat cat;
Fox fox;
whatDoesItSay("cat", &cat);
whatDoesItSay("fox", &fox);
}