Я играл с наследованием и пробовал этот код:
#include <iostream>
#include <string>
class Foo
{
public:
virtual void func() = 0;
protected:
virtual void doSum() const = 0;
};
class Bar : public Foo
{
public:
void func() {
doSum();
}
protected:
void doSum() const
{
std::cout << "hi, i'm doing something" << std::endl;
}
};
int main()
{
Foo* ptr = new Bar();
ptr->func();
return 0;
}
Поэтому я также попытался заменить ключевое слово protected
в class Bar
на private следующим образом:
private:
void doSum() const
{
std::cout << "hi, i'm doing something" << std::endl;
}
и код работал точно так же...
Итак, мой вопрос: есть ли разница, если я объявлю защищенный метод закрытым при реализации производного класса? Если так, то кто они? Мне вообще разрешено это делать?
So my question is, is there any difference if I declare a protected method private when implementing a derived class?
Нет. Нет никакой разницы. К сожалению, стандарт C++ не налагает никаких требований на производный класс, чтобы помещать переопределяющую виртуальную функцию в какую-либо конкретную область доступности. Это означает, что базовый класс может объявить виртуальный метод защищенным, а производный класс может реализовать метод в общедоступной/защищенной/приватной области, и код все равно будет легальным и будет работать.
So my question is, is there any difference if I declare a protected method private when implementing a derived class?
да.
If so, what are they?
Это предотвратит возможность следующего уровня производного класса вызывать реализацию производного класса.
class Foo
{
protected:
virtual void doSum() const = 0;
};
class Bar : public Foo
{
private:
void doSum() const
{
std::cout << "hi, i'm doing something" << std::endl;
}
};
class Baz : public Bar
{
public:
void doSum() const
{
//===========================
Bar::doSum(); // NOT ALLOWED
//===========================
}
};
Am I even allowed to do this?
да.
Спасибо за подробный ответ! Итак, если я не собираюсь получать Bar, должен ли я оставить его защищенным или сделать его частным? Или в буквальном смысле не имеет значения?
@Grybouilli, если ты абсолютно уверен, то да, тогда это не имеет значения.
@Grybouilli «Итак, если я не собираюсь получать Bar, мне лучше оставить его защищенным или сделать его частным?» - Если вы не хотите, чтобы можно было получить из Bar
, вы должны сделать класс final
. Вы также можете создавать отдельные функции final
, чтобы предотвратить их переопределение, в то же время позволяя другим производным от Bar
.
Конечно. но
fooPtr->doSum()
все равно вызовет реализациюBaz
.