質問

I am trying to support a copy function in some of my classes and to do so I created a base class (an interface). But in addition to that class I have another class that inherits from it and needs to override the "copy" function and provide a new return type. The way that I am copying the class is by using a wrapper class to automatically delete the pointer to the newly allocated object when it is no longer used. It is a templated class which does not qualify as a covarient type. What I just described looks a lot like this:

template <T>
struct BASE {
    virtual PTR<BASE> copy() const = 0;
};

template <Y>
struct DERIVED : public BASE<Y> {
     virtual PTR<DERIVED> copy() const = 0; // ERROR: PTR<DERIVED> not a covarient type to PTR<BASE>.
};

Knowing that this is not legal in C++, I was wondering if I could do something similar to this such as:

template <T>
struct DERIVED : public BASE<T> {
    virtual PTR<DERIVED> DERIVED::copy() const = 0; // Derived classes should override this function and act as if "PTR<BASE<T>> BASE<T>::copy() const" does not exist.

    private: // hide function so that "PTR<DERIVED>" function is called, but when dealing with the base class call the following function.
    PTR<BASE<T>> BASE<T>::copy() const {
         return PTR<BASE<T>>((BASE<T>*)DERIVED::copy()->GetAndRelease()); // Convert the "PTR<DERIVED>" object to a "PTR<BASE<T>>" object.
    }
};

The code above does not compile because you cannot name the class your in when defining it in a class. EX: can't do "DERIVED::copy" while in the class and defining a function, at least G++ gives me an error when I do it. It is worth mentioning that the "PTR" class mentioned works something like this:

template <T>
struct PTR {
    PTR(T* ptr); // set the pointer to the data;
    ~PTR(); // destroy the object pointed to by "ptr";

    T* get(); // get the pointer to the data;
    T* GetAndRelease(); // just to simplify the example, this function returns the pointer and makes it so that the class does not delete the pointer when it is deconstructed.

    private:
    T* ptr;
}
役に立ちましたか?

解決

You can't overload based on the return type. The simple solution is to not make the copy() function the virtual interface but rather have it just call the virtual interface:

class Base {
    Base* do_copy() const = 0;
public:
    smart_ptr<Base> copy() const { return smart_ptr<Base>(this->do_copy()); }
};
class Derived {
     Derived* do_copy() const { return new Derived(*this); }
public:
     smart_ptr<Derived> copy() const { return smart_ptr<Derived>(this->do_copy()); }
};

The idiom of not making virtual functions public is used quite consistently in the standard library (I think the exception is std::exception::what()). It also conveniently side-steps the issue of an override hiding other overloads (see, e.g., the put() and do_put() members of std::num_put<...>).

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top