#c #class #inheritance #static #abstract-class
#c #класс #наследование #статические #абстрактный класс
Вопрос:
Я пришел из C # и теперь пытаюсь освоить C . Я использую абстрактный класс со статическим членом для отслеживания общего числа объектов этого типа и статический метод для получения количества. например:
class Shape
{
public:
virtual void Draw() = 0;
static int GetShapeCount();
private:
static int mShapeCount;
};
Я заметил, что производные классы также могут вызывать статический метод абстрактного класса, который я нашел немного любопытным / запутанным. Например, кто-то может запутаться, если он сможет сделать что-то вроде:
Shape *newShape = new Rectangle();
cout << newShape->GetShapeCount();
Означает ли это получить количество прямоугольников или количество фигур? Я также заметил, что даже если вы явно не называете это формой, вы все равно можете получить доступ к статическому методу через производные классы:
Rectangle rectClass = Rectangle();
cout << rectClass.GetShapeCount();
Итак, мой вопрос двоякий:
1) Почему / как это возможно
2) Есть ли способ запретить производным классам вызывать статические методы абстрактного класса?
Редактировать:
мой тест, который я запускал в C #, был неверным, и он показывает аналогичное поведение … мне просто кажется странным, что статические методы также будут передаваться производным классам. Это кажется совместимым с другими языками, и я полагаю, что я просто допустил ошибку.
Комментарии:
1. Это общедоступный метод, он не скрыт ни от чего в вашем коде. Почему это должно быть скрыто от производных классов?
2. мой вопрос в том, почему я могу вызвать статический метод в абстрактном классе из производного класса, а не почему он не скрыт
3. @DavidTorrey (public) статические методы — это статические методы, это статические методы, точка! «Есть ли способ запретить производным классам вызывать статические методы абстрактного класса?» Да, создайте метод
private
илиprotected
!4. @DavidTorrey «… в C # быстрый тест показывает» Использование тестового кода c # вряд ли воспроизведет какое-либо поведение c !
5.
Does that mean get rectangle count or shape count?
Почему это сбивает с толку? Это называется «GetShapeCount», поэтому кажется довольно очевидным, что это количество фигур.
Ответ №1:
Нет, в C нет полиморфных статических функций, поэтому предположим static getShapeCount()
, что он был реализован как return mShapeCount;
, он вернет значение базового класса. Однако это можно легко смоделировать, используя CRTP и статический полиморфизм. Поскольку не рекомендуется вызывать статические функции из объектов вместо самого класса, это работает как шарм.
Я также заметил, что даже если вы явно не называете это формой, вы все равно можете получить доступ к статическому методу через производные классы
Вы объявили getShapeCount()
об этом публично, не так ли? И вы (я полагаю, опять же, потому, что вы не показали нам достаточно кода) использовали публичное наследование.
Комментарии:
1. но почему я могу вызвать этот статический метод из производного класса?
2. разве я не должен иметь возможность вызывать статический метод только из формы базового класса? Я не понимаю, почему я мог бы вызвать статический метод Shape из Rectangle
3. @DavidTorrey почему? Вы объявили функцию как
public
. Вы унаследовали базовый класс, используя общедоступное наследование. Таким образом, ваш производный класс имеет доступ к методу базового класса. И поскольку он общедоступен на базе, он общедоступен на производном. Обратите внимание, что это точно такое же поведение C #…4.
I don't see why i'd be able to call the Shape static method from Rectangle
В этом вся цель наследования. Я не понимаю, почему это так сбивает вас с толку.5. полагаю, я думал, что наследование отличается для статических методов
Ответ №2:
Shape *newShape = new Rectangle();
cout << newShape->GetShapeCount();
это способ писать cout << Shape::GetShapeCount()
.
как
Rectangle rectClass = Rectangle();
cout << rectClass.GetShapeCount();
это способ написания cout << Rectangle::GetShapeCount()
, который превращается в Shape::GetShapeCount()
.
Если вы хотите запретить Rectangle::GetShapeCount()
, вы можете добавить удаленную функцию (C 11):
class Rectangle : public Shape
{
public:
// Previous methods
static int GetShapeCount() = delete; // forbid the usage Rectangle::GetShapeCount()
};
Комментарии:
1. 1 Я рад видеть, что времена, когда C 11 считается C , а не другой версией только для фриков, начались. Ну, три года потрачено, не так ли?
Ответ №3:
Я заметил, что производные классы также могут вызывать статический метод абстрактного класса, который я нашел немного любопытным / запутанным.
Это то же поведение, что и в C #: производные классы имеют доступ ко всем методам своего базового класса, если это позволяет их видимость (общедоступная, защищенная, внутренняя и т. Д.).
Означает ли это получить количество прямоугольников или количество фигур?
Это счетчик формы, потому что все производные классы используют один и тот же счетчик.
Есть ли способ запретить производным классам вызывать статические методы абстрактного класса?
Да — вы можете скрыть метод от производных классов , создав его private
.
Если вы хотите сохранить отдельные счетчики объектов для каждого производного класса, вы можете создать статический map<type_index,int>
и увеличить счетчик вашего конкретного типа. Однако вам необходимо предоставить вашему static
методу доступ к типу вызывающего объекта.
Комментарии:
1. «вы можете создать статическую карту<type_index,int> и увеличить счетчик вашего конкретного типа». Этого можно легко достичь с помощью CRTP, нет необходимости в RTTI.
2. да. Вы правы. Извините. Смысл был в том, чтобы не использовать RTTI для этого. С другой стороны, это другой способ решить эту проблему, и, возможно, проще для нобелей C .