1

I'm investigating cross platform library published by dropbox. following java code is from it. And i want to implement same thing in my Visual c++; First Look at java code

public abstract class AsyncTask 
{
    public abstract void execute();

    public static final class CppProxy extends AsyncTask
    {
        private final long nativeRef;
        private final AtomicBoolean destroyed = new AtomicBoolean(false);

        private CppProxy(long nativeRef)
        {
            if (nativeRef == 0) throw new RuntimeException("nativeRef is zero");
            this.nativeRef = nativeRef;
        }

        private native void nativeDestroy(long nativeRef);
        public void destroy()
        {
            boolean destroyed = this.destroyed.getAndSet(true);
            if (!destroyed) nativeDestroy(this.nativeRef);
        }
        protected void finalize() throws java.lang.Throwable
        {
            destroy();
            super.finalize();
        }

        @Override
        public void execute()
        {
            assert !this.destroyed.get() : "trying to use a destroyed object";
            native_execute(this.nativeRef);
        }
        private native void native_execute(long _nativeRef);
    }
}

This java code calls some jni c++ class (it is same name of AsyncTask). So it is implementing c++ proxy inside java class to maintain jni side c++ Object.

But i want to do it in MFC c++ language, not java language (usually for testing purpose) So i implemented c++ class from upper java code. But i have found c++ doesn't have static class definition. Folloing code shows error

class AsyncTask 
{
    public:
    virtual void execute();

    public static class CppProxy : public AsyncTask 
    {
        private:
        long LocalNativeRef;

        CppProxy(long tmpNativeRef)
        {

        }

        void execute()
        {

        }
    };
};

So How can i implement inner static class which is subclsssing outside class.

Knowledge Drilling
  • 986
  • 1
  • 8
  • 22

2 Answers2

1

You cannot derive from an incomplete class, and AsyncTask is incomplete until its definition is complete. That's why class CppProxy : public AsyncTask fails.

The solution is easy, though. Just make the CppProxy class a completely separate one, and get rid of the redundant public, too. If you need to access private members of CppProxy from AsyncTask (otherwise, I'm not sure what the purpose of the static Java class would be in the first place), then use a friend declaration.

Here is an example:

class AsyncTask 
{
    public:
    virtual void execute();

    friend class CppProxy;
};

class CppProxy : public AsyncTask 
{
    private:
    long LocalNativeRef;

    CppProxy(long tmpNativeRef)
    {

    }

    void execute()
    {

    }
};

Note that you can, and should use override like in Java if you are using a C++11-enabled compiler. And you apparently need a virtual destructor in AsyncTask.

Christian Hackl
  • 27,051
  • 3
  • 32
  • 62
1

Ok so you are trying to translate Java to C++.

In java an inner class has by default a hidden pointer to an object of enclosing class. Making it static removes that hidden pointer - said differently, it is no longer bound to a containing object so static => no direct equivalent in C++ and C++ inner classes are static in that sense

In C++, you cannot derive from an incomplete class: an inner class cannot derive from its enclosing class => you must put the CppProxy class declaration outside of AsyncTask. If you do not want to put it in global namespace, you could put it in another namespace say AsyncTaskInner

Except in very special cases in C++, a class intended to be derived should have a virtual destructor to allow proper destructor calling when you delete a pointer to a base class => you must add a virtual destructor to class AsyncTask.

In C++ you do not declare a class to be abstract, but you can make it abstract if it contains a pure virtual method => declare execute as pure virtual

You end with something like:

class AsyncTask 
{
public:
    virtual void execute() = 0;
    virtual ~AsyncTask() {}
};


namespace _AsyncTaskInner {
    class CppProxy : public AsyncTask 
    {
    private:
        long LocalNativeRef;
    public:

        CppProxy(long tmpNativeRef)
        {

        }

        void execute()
        {

        }
    };
}
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
  • Thanks for your kind and detail answer. – Knowledge Drilling Mar 04 '16 at 12:47
  • @MomAndDad: Do not forget to accept one of the answers (check the mark) to notify future readers that you no longer need help with your question. Question with no accepted answers are considered as not closed in Stack Overflow. – Serge Ballesta Mar 04 '16 at 13:23