有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

c#计算每个派生类的类实例

有没有办法让所有派生类都计算它们的实例?如何编写C++、C、java中的代码?

假设我有权访问根类(例如object),而其他所有类(直接或间接)都是从这个类派生的。我想要的是:

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个derived1类实例和8个derived2类实例,则有(a)15个object实例或(b)0个object实例。我不在乎哪一个,因为我两个都做不到(使用合理实用的方法,例如想象100个类,其中一半在库中,我无法修改)

当然,从理论上讲,可以创建(某些运行类型标识符)=>;int计数,并使用丑陋、缓慢(运行时类型)的方法(至少在C#和Java中)

当然,如果我可以修改派生类,我可以使用复制粘贴(糟糕)、宏(是的,我知道)、混合(不在这些语言中)等等,但这仍然非常难看

这是一个特定的问题,但我也遇到过好几次,我希望能够将静态成员“注入”到派生类中,以优雅地解决问题

非常感谢你的帮助

<>编辑:谢谢你的好回答,在C++中,也可能使用CRTP(奇怪的重复模板模式),但是不使用C语言/ java(没有多重继承)。当然,必须有权访问派生类并添加这个基类,所以问题仍然存在(如果没有其他方法,这看起来是最好的)

编辑2:使用当前语言看起来不可能。每个类的静态部分都不是继承的(没错),但没有与每个类相关联的继承单例,因此这些问题无法如此优雅地解决。 为了说明这一点,请看下面的代码:普通成员和静态成员是当前的OOP语言功能,“singleton”(或任何单词)成员是我的建议/愿望:

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; }
};

共 (2) 个答案

  1. # 1 楼答案

    我会使用模板。这是C++的,顺便说一下。p>

    template<typename T> class object {
    private:
        static int count;
    public:
        object() { count++; }
        object(const object&) { count++; }
        ~object() { count--; }
        static int GetCount() { return count; }
    };
    template<typename T> int object<T>::count = 0;
    

    RTTI解决方案:

    class object {
        static std::map<std::string, int> counts;
    public:
        object() { counts[typeid(*this).name()]++; }
        object(const object&) { counts[typeid(*this).name()]++; }
        ~object() { counts[typeid(*this).name()]--; }
        template<typename T> int GetObjectsOfType() {
            return counts[typeid(T).name()];
        }
        int GetObjectsOfType(std::string type) {
            return counts[type];
        }
    };
    std::map<std::string, int> object::counts;
    

    RTTI的侵入性较小,允许在运行时选择要查询的类型,但模板的开销要小得多,您可以使用它单独计算每个派生类,而RTTI只能单独计算派生最多的类

  2. # 2 楼答案

    在Java中,可以使用全局Multiset

    import com.google.common.collect.ConcurrentHashMultiset;
    
    public abstract class InstanceCounted {
    
        protected InstanceCounted() {
            COUNT_MAP.add(this.getClass());
        }
    
        protected static final ConcurrentHashMultiset<Class<? extends InstanceCounted>> COUNT_MAP =
            ConcurrentHashMultiset.create();
    
    }
    

    或者,如果你不想依赖番石榴,你可以使用Map<Class, Integer>

    注意:这只跟踪实例创建,而不是垃圾收集,因此计数永远不会减少。如果您愿意受到性能影响,还可以使用PhantomReference跟踪收集:

    import java.lang.ref.PhantomReference;
    import java.lang.ref.Reference;
    import java.lang.ref.ReferenceQueue;
    
    import com.google.common.collect.HashMultimap;
    import com.google.common.collect.Multimap;
    import com.google.common.collect.Multimaps;
    
    public abstract class InstanceCounted {
    
        public static int getInstanceCount(Class<? extends InstanceCounted> clazz) {
            reap();
            return INSTANCES.get(clazz).size();
        }
    
        protected InstanceCounted() {
            reap();
            INSTANCES.put(getClass(), new CountingReference(this));
        }
    
        static final Multimap<Class<? extends InstanceCounted>, CountingReference> INSTANCES =
            Multimaps.synchronizedSetMultimap(HashMultimap.<Class<? extends InstanceCounted>, CountingReference>create());
    
        static final ReferenceQueue<InstanceCounted> QUEUE =
            new ReferenceQueue<InstanceCounted>();
    
        private static void reap() {
            Reference<? extends InstanceCounted> ref;
            while ((ref = QUEUE.poll()) != null) {
                ((CountingReference) ref).clear();
            }
        }
    
        private static class CountingReference extends PhantomReference<InstanceCounted> {
    
            public void clear() {
                super.clear();
                INSTANCES.remove(clazz, this);
            }
    
            CountingReference(InstanceCounted instance) {
                super(instance, QUEUE);
                this.clazz = instance.getClass();
            }
    
            private final Class<? extends InstanceCounted> clazz;
    
        }
    
    }