Pergunta

Sorry in advance if this topic has been raised and solved before.

I would like to create a base class with a pure virtual function (abstract class) such that when creating a derived class from it, the user is obliged to implement the body of this function in the derived class. The point is that in the pure virtual function, I would like to have as argument objects of the derived type. Is that possible ?

For instance:

class Base{

 public:
  virtual void DoSomething (A object1, B object2) = 0;
};

class A: public Base{

 public:
  DoSomething(A x, B y) {

   ...
   ...
};

};

class B: public Base{

 public:
  DoSomething(A x, B y) {

   ...
   ...
};

};

I tried but the compiler complains saying that it knows nothing about the derived classes, which I understand since they are created after the Base class. Is there a way to circumvent ? Or is there another way to do what I want, that is, to oblige the user to implement the body of the function in the derived class with arguments arguments object of derived class type ?

Thanks in advance !

Foi útil?

Solução 2

EDIT: final version using const references :-)

///Test-code. place anywhere in global C++ scope for testing
class A;
class B;

class Base{

 public:
  virtual void DoSomething ( const A & object1, const B & object2) = 0;
};

class A: public Base{

 public:
  void DoSomething(const A & object1, const B & object2) { 
    int i=0;
    i++; //test break point
  };

};

class B: public Base{

 public:
  void DoSomething(const A & object1, const B & object2) { 
    int i=0;
    i++; //test break point
  };

};

bool test()
{
    A a;
    B b;

    a.DoSomething( A(), B() );
    b.DoSomething( A(), B() );
    return true;
}

static bool invokeTest = test();
///END of test-code

EDIT: better version using auto_ptr

///Test-code. place anywhere in global C++ scope for testing
#include <memory>
using std::auto_ptr;
class A;
class B;




class Base{

 public:
  virtual void DoSomething (auto_ptr<A> object1, auto_ptr<B> object2) = 0;
};

class A: public Base{

 public:
  void DoSomething(auto_ptr<A> x, auto_ptr<B> y) { 
    int i=0;
    i++; //test break point
  };

};

class B: public Base{

 public:
  void DoSomething(auto_ptr<A> x, auto_ptr<B> y) { 
    int i=0;
    i++; //test break point
  };

};

bool test()
{
    Base *a = new A;
    Base *b = new B;

    a->DoSomething( auto_ptr<A>(new A), auto_ptr<B>(new B) );
    b->DoSomething( auto_ptr<A>(new A), auto_ptr<B>(new B) );
    return true;
}

static bool invokeTest = test();
///END of test-code

Original answer

If the arguments are pointers, then it should work:

class A;
class B;

class Base{

 public:
  virtual void DoSomething (A * object1, B * object2) = 0;
};

class A: public Base{

 public:
  void DoSomething(A *x, B *y) {

};

};

class B: public Base{

 public:
  void DoSomething(A *x, B *y) {

};

};

P.S.:I wonder why you would need it?

EDIT P.P.S.: I still wonder why one would need it :-)?

Outras dicas

Use reference and forward declaration:

// Forward declaration
class A;
class B;

class Base
{
public:
    virtual void DoSomething(const &A a, const B& b) = 0;
};

class A: public Base
{
public:
    virtual void DoSomething(const &A a, const B& b) /* override */;
};

Yes, but you need templates.

class AbstractBase
{
}

template <typename D>
class Base : public AbstractBase
{
public:
    virtual D* func() = 0;
};

class Derived : public Base<Derived>
{
public:
    Derived* func() { return this; }
};

You end up with a template instantiation of Base for each derived type. This means that if you have class Derived1 : public Base<Derived1> and class Derived2 : public Base<Derived2>, then they do not share the same Base class; but since Base<T> inherits from th non-templated AbstractBase, they both inherit from that. (And, of course, you can inherit from Derived in the normal way.)

Thanks a lot for the prompt answer ! The solution with const ref works well ! Someone was asking why one would need something like that. I'll try to explain shortly. I'm physicist and I'm trying to implement some interaction between objects.

The Base class should contain some common stuff to the objects. The derived class (A, B, ...) should represent objects with different properties. Then, I try to implement the physics of each object type (derived class) and its interaction with the other objects (the other derived class). A can react with B or C, B with A, C, or D, etc...

Since each object has its own physics and each interaction can be different, one cannot implement the body of the DoSomething function in the Base class. Therefore, I use a pure virtual function in the Base class.

For instance, A could interact with objects of class B or class C. Then, I should have in the Base class virtual void DoSomething(const A & object1, const B & object1) = 0; virtual void DoSomething(const A & object1, const C & object1) = 0;

and then I override the function twice in the derived class A. And so on for the other derived classes.

Do you think it could be done in some other and smarter way ?

Thanks !

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top