Есть ли способ заставить все производные классы считать свои экземпляры? Как (писать код в одном из С++, С#, Java)?
Представьте, что у меня есть доступ к корневому классу (например, к объекту), и каждый другой класс (прямо или косвенно), полученный из этого класса. Я хочу:
AnyDerivedClass.InstancesCount()
Проблема заключается в том, что нужно отслеживать счет в статической переменной, но невозможно "вводить" статическую переменную в производный класс из базового класса, это относится только к переменным-членам. То есть, я должен написать что-то вроде:
class object
{
private static int count = 0;
protected object() { ++count; }
protected ~object() { --count; }
public static InstancesCount() { return count; }
};
class derived : object
{
private static int count = 0;
public derived() { ++count; }
public ~derived() { --count; }
public static InstancesCount() { return count; }
}
Эта функциональность явно повторяется, и я не могу поместить ее в базовый класс. Обратите внимание, что есть два способа вычисления: если есть 7 экземпляров класса производных 1 и 8 экземпляров класса производных2, существует (а) 15 экземпляров объекта или (b) 0 экземпляров объекта. Меня не волнует, какой из них, потому что я не могу этого сделать (используя разумно практические средства, например, представить 100 классов, половина из которых находится в библиотеке, которую я не могу изменить).
Конечно, теоретически возможно создание карты (некоторый идентификатор типа запуска) = > int count и использование уродливого, медленного (на основе времени) подхода (по крайней мере, на С#, Java).
Конечно, если я могу модифицировать производные классы, я могу использовать copy-paste (ужасный), макрос (да, я знаю), mixins (не на этих языках) и т.д. Но это по-прежнему очень уродливо.
Это конкретная проблема, но это случилось со мной несколько раз, что я хотел бы иметь возможность "вставлять" статический член в производный класс для решения проблемы элегантно.
Помогите оценить.
EDIT: спасибо за хороший ответ, на С++ возможно использовать CRTP (Curiously recurring template pattern), но не в С#/Java (без множественного наследования). Конечно, нужно иметь доступ к производным классам и добавлять этот базовый класс, поэтому вопрос остается (в противном случае это выглядит лучше).
РЕДАКТИРОВАТЬ 2: выглядит невозможно с текущими языками. статическая часть каждого класса не наследует (и это право), но нет никакого наследующего синглтона, связанного с каждым классом, поэтому такие проблемы не могут быть решены так элегантно. Чтобы проиллюстрировать это, посмотрите на следующий код: обычные члены и статические члены - это текущая функция языков ООП, "одиночный" (или любое другое слово) - это мое предложение/желание:
class Base
{
static int sMemberBase;
int memberBase;
//my wish (note that virtual for methods is allowed!):
singleton int singletonMemberBase;
};
class Derived : Base
{
static int sMemberDerived;
int memberDerived;
//my wish (note that virtual for methods is allowed!):
singleton int singletonMemberDerived;
};
//taken apart: (note: XYZStatic classes do not derive)
class Base { int memberBase; }
class BaseStatic { int sMemberBase; } BaseStaticInstance;
class Derived : Base { int memberDerived; }
class DerivedStatic { int sMemberDerived; } BaseStaticInstance;
//note: Derived::sMemberBase is compile-time changed to Base::sMemberBase
//my wish: (note inheritance!)
class BaseSingleton { int singletonMemberBase; } BaseSingletonInstance;
class DerivedSingleton : BaseSingleton { int singletonMemberDerived; } DerivedSingletonInstance;
Если что-то подобное будет присутствовать на языке, решение для моего вопроса будет простым и изящным:
//with singleton members, I could write counter like this:
class object
{
singleton int count;
object() { ++count; }
~object() { --count; }
};