A method in a base class that returns the type of a derived class?

I have a group of classes that have one common function, except that it returns a pointer to its own type. The code looks the same and I would like to move it to an abstract base class. But how can I get classes that inherit from it to return my own type?

class base {
    base *foo() {
        // ...
    }
};


class derived : public base {

};

derived d;
d.foo(); // Should return derived* instead of base*

Is there any way to express this in C ++?

+4
source share
2 answers

Yes, C ++ supports this. It was called covariant return types. You just need to declare a virtual function and declare return types accordingly. That is all that is needed.

struct base {
    virtual base *foo() {
        // ...
    }
};


struct derived : public base {
    virtual derived *foo() {
        // ...
    }
};

derived d;
base *base_ptr = d.foo();

:

- , , .

.

, , , , , .

, ; . .

// beware of macros!
#define FOO(T) virtual T *foo() { return new T; }

struct base {
    FOO(base)
    virtual ~base() {} // let not forget the virtual destructor
};


struct derived : public base {
    FOO(derived)
};

, :

template <class T>
T *ComplicatedFunctionReturningT()
{
    T *t;
    // ...
    // ...
    // ...
    return t;
}

struct base {
    virtual base *foo() {
        return ComplicatedFunctionReturningT<base>();
    }
    virtual ~base() {} // let not forget the virtual destructor
};


struct derived : public base {
    virtual derived *foo() {
        return ComplicatedFunctionReturningT<derived>();
    }
};

, .


- . , :

class base {
public:
    base *foo() { // no longer virtual
        // ...
        // ...
        base *ptr = fooImpl();
        // ...
        // ...
        return ptr;
    }

    virtual ~base() {} // let not forget the virtual destructor

private:
    virtual base *fooImpl() = 0; // pure virtual and private
};

class derived1 : public base {
private:
    virtual derived1 *fooImpl() {
        return new derived1; // very simple body
    }
};

class derived2 : public base {
private:
    virtual derived2 *fooImpl() {
        return new derived2; // very simple body
    }
};

, , . ++ - script.

, , , . , , , , .

+9

, , , :

class base 
{
  protected:
    template<class T> T* fooInternal()
    {
        T* t = new T();

        // do stuff with t

        return t;
    }
  public:
    virtual base* foo() { return fooInternal<base>(); }
};


class derived : public base 
{
  public:
    virtual derived* foo() { return fooInternal<derived>(); }
};
+2

All Articles