tags:

views:

348

answers:

6

Hello,

I want to create a generic var, that could be from one class or another class.

In this code sample I want that var aa be generic so in my code I can access code from class A or class B.

But aa MUST BE GLOBAL.

Could you help me?

class MyClass
{
public:
    MyClass() {} //contructor padrão, não deve ser utilizado isoladamente

    static MyClass* getInstance()
    {
        static MyClass *instance = 0;
        if (!instance) instance = new MyClass();
            return instance;
    }
};

class A : public MyClass
{
public:
    int a() { return 1; }
};

class B : public MyClass
{
public:
    int b() { return 1; }
};

template <class TAIT> class AIT
{
public:
    static TAIT& Instance()
    {
        static TAIT instance;
        return instance;
    }
};

AIT aa;

void main()
{
    aa.Instance().a(); // or
    aa.Instance().b(); // aa could be class
                       // A or class B. So I could access
                       // function a or function b (not at same
                       // time, of course)

    return;
}
+1  A: 

Declare a pure virtual in the base class, overload it in the derived classes.

class MyClass {
public:
   virtual int a() = 0;
};

class DerivedA : public MyClass {
public:
   virtual int a() { return 1; }
};

Both derived classes will have a method with the same name and you will resolve automatically which method to call depending on the object type. You will have to rewrite the creation part of the GetInstance() method for it to know what class instance to create.

sharptooth
+2  A: 

If I understand you correctly, I think that you just need to declare aa correctly, and you're set:

AIT<A> aa;
aa.Instance().a();

AIT<B> bb;
bb.Instance().b();

If that isn't what you mean, please edit your question and clarify what you're trying to do.

Andy
+7  A: 

Short answer:

C++ template give you compile-time genericity, not runtime genericity.

Templates by themselves have no existence in your program (that is as a concrete binary executable). They will end up as generated code only when instantiated by specifying their arguments either explicitly or implicitly.

So, this does NOT declare a variable:

AIT aa;

This declares a variable:

AIT<A> aa;

If you need runtime genericity, you have to use a runtime dispatch mechanism:

  • either do it manually with a switch case.
  • or better use the builtin inheritance of a common base class + some virtual methods.
bltxd
A: 

If you don't want your constructor be called other than from in your getInstance method, you can make it private. e.g.

class MyClass
{
private:
    MyClass() {} //contructor padrão, não deve ser utilizado isoladamente
public:
    static MyClass* getInstance()
    {
        static MyClass *instance = 0;
        if (!instance) instance = new MyClass();
            return instance;
    }
};

Now

MyClass* a = new MyClass();

Will cause a compile error because your constructor is private

Nick
A: 

Is this a good solution for this problem?

class MyClass { public: MyClass() {} //contructor padrão, não deve ser utilizado isoladamente virtual int a() = 0; virtual int b() = 0;

int c() { return b(); }

   static MyClass* getInstance()
   {
      static MyClass *instance = 0; //          if (!instance) instance

= new MyClass(); return instance; } };

class A : public MyClass { public: int a() { return 1; } int b() { return 1; } int d() { return 1; } };

class B : public MyClass { public: int a() { return 1; } int b() { return 1; } int e() { return 1; } };

class C : public A, public B { public: A ca; B cb;

enum TIPO { A, B }; TIPO Tipo;

C(TIPO tipo) { Tipo = tipo; }

int a() { switch(Tipo) { case A: return ca.a(); break; case B: return cb.b(); break; default: break; } }

};

void main() { //MyClass* A = MyClass::getInstance(); //MyClass* B = MyClass::getInstance();

C c(C::B); c.a(); // aa.Instance().a(); // aa.Instance().b();

return; }

A: 

It's definitely nasty, but perhaps the solution here is to use a void pointer. In C and C++, a pointer declared as void* is defined to have no type. You can pass this pointer around and then cast it to a pointer of whatever datatype you wish. Obviously it is crucial to very carefully ensure that the variable is actually of the right type, but if you are designing an interface where you don't know the return type, this can be useful. Here's an example of how the interface class might look:

class InterfaceClass {
  public:
     virtual void* someInterface() = 0;
}

You can then create another class that implements the interface and does whatever interesting things you want:

class DerivedClass: public InterfaceClass {
  public:
     virtual void* someInterface() {
        //do some stuff
        return (void*) somePointer;

}

As long as any code you have understands what to do, you can pass back whatever type of pointer you want. There's plenty of more information if you search Google for void pointers. Be careful.

spectre256