简体   繁体   中英

Use a derived class type as parameter of a base method in C++

I have the following classes in the following files:

    // Tensor.hh
    template <class T>
    class Tensor {
        /* declarations */
    }

    // Tensor.cpp
    #include "Tensor.hh"
    // Implementation of Tensor.hh

    // Kernel.hh
    #include "Tensor.hh"
    template <class T>
    class Kernel : public Tensor<T> {
       /* declarations */
    }

    // Kernel.cpp
    #include "Kernel.hh"
    // Implementation of Kernel.hh

Is it possible to use a pointer to "Kernel" as parameter of a "Tensor" method? Something like:

    template <class T>
    void Tensor<T>::foo(Kernel<T>* kernel) {
        // Do something...
    }

Yes it is possible. In your Tensor.cpp you will have to include #include "Kernel.hh" , and in your Tensor.hh you will have to add a forward declaration:

template<typename>
class Kernel;

Usually I would really avoid forward declaring template classes, and I would avoid circular dependencies. Sometimes they are not avoidable, but sometimes yes.

Another solution would be to simply implement foo as a free function in another header:

void foo(Tensor<T>& tensor, Kernel<T>* kernel) {
    // ...
}

That way you break the circular dependency, and you get bonus encapsulation.

I think you need to use forward declaration of the class Kernel. I could compile following:

 template <class T>
    class Kernel;


 template <class T>
    class Tensor {
        /* declarations */
     void foo(Kernel<T>* kernel);
    };

 template <class T>
    class Kernel: public Tensor<T> {
    };

The implementation of your class templates needs to be visible to your users. So it's best to put the implementation directly in the header file.

// Forward declare Kernel<T> so Tensor<T> can know about it for foo()
template<typename T>
class Kernel;

// Define Tensor<T>
template<typename T>
class Tensor {
    void foo(Kernel<T>* kernel);
    ...
};

// Define Kernel<T>
template<typename T>
class Kernel : public Tensor<T> {
    ...
};

// Define Tensor<T>::foo here since Kernel<T> needs to be defined
// for it to do anything meaningful with it
template<typename T>
void Tensor<T>::foo(Kernel<T> *kernel) {
    // Do something...
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM