Статические методы абстрактного класса C , отображаемые в производных классах

#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 .