【问题标题】:Generic template for nested abstract base classes嵌套抽象基类的通用模板
【发布时间】:2017-09-28 12:14:16
【问题描述】:

我正在尝试创建一个可用于模板其他类的类。也许我正在寻找错误的关键词。本质上,我希望PrimaryClassA 类是纯虚拟的。 DerivedClassC 派生自它们各自的类。 问题是通过调用继承类:C in DerivedClass 我没有覆盖纯虚拟PrimaryClass。我知道这一点,但我不知道如何解决它。

我的印象是,因为C 是从A 派生的,所以它会起作用。 如果我在

中更改C
virtual void DoFunThings ( C<T>* d ) {}

A 它可以工作,但这样做的目的是允许使用A 的不同派生版本。

template <class T>
class A
{
public:  
    virtual void FunThings ( const A<T> &orig, A<T>* new_one ) = 0;   
    T thing{};
};


template <class T>
class C: public A < T >
{
public:
    virtual void FunThings ( const C<T> &orig, C<T>* new_one ) {}

};


template <class T>
class PrimaryClass
{
public:    
    virtual void DoFunThings ( A<T>* d ) = 0;
};



template<class T>
class DerivedClass: public PrimaryClass<T>
{
public:
    virtual void DoFunThings ( C<T>* d ) {}
};


int main ()
{
    DerivedClass<int> derived;

    return 0;
}

如果无法做到这一点,如何才能编写具有我想要的功能的通用面向对象代码?

【问题讨论】:

    标签: c++ inheritance derived-class generic-programming


    【解决方案1】:

    您可以使用一些机器和模板以某种方式模拟虚拟功能模板,并获得非常接近您正在寻找的东西(可能)。
    举个例子:

    #include<type_traits>
    #include<iostream>
    
    template <class T>
    class A {};
    
    template <class T>
    class B: public A < T > {};
    
    template <class T>
    class C: public A < T > {};
    
    template <class>
    class PrimaryClass;
    
    template <typename T, template<typename> class U>
    class PrimaryClass<U<T>>
    {
        template<typename D, typename Z = U<T>>
        auto DoFunThings(int, D *d)
        -> decltype(static_cast<Z*>(this)->DoFunThingsOverride(d)) {
            return static_cast<Z*>(this)->DoFunThingsOverride(d);
        }
    
        void DoFunThings(char, A<T> *) {
            // do whatever you want if
            // derived class has not a
            // proper specialization
            std::cout << "PrimaryClass::DoFunThings" << std::endl;
        }
    
    public:
        template<typename D>
        std::enable_if_t<std::is_base_of<A<T>, D>::value, void>
        DoFunThings ( D* d ) {
            DoFunThings(0, d);
        }
    };
    
    template<class T>
    class DerivedClass: public PrimaryClass<DerivedClass<T>>
    {
    public:
        void DoFunThingsOverride ( C<T>* ) {
            std::cout << "DerivedClass::DoFunThings" << std::endl;
        }
    };
    
    
    int main ()
    {
        DerivedClass<int> derived;
        B<int> b;
        C<int> c;
    
        derived.DoFunThings(&b);
        derived.DoFunThings(&c);
    
        return 0;
    }
    

    查看wandbox

    【讨论】:

      【解决方案2】:

      解决方案是给 PrimaryClass 和 DerivedClass 模板提供的不是 A 和 C 的唯一数据类型(问题中为 int),而是 A 和 C 类。

      template <class D>
      class PrimaryClass
      {
      public:
      
          virtual void DoFunThings ( D* d ) = 0;
      };
      
      
      
      template<class D>
      class DerivedClass: public PrimaryClass<D>
      {
      public:
          virtual void DoFunThings ( D* d ) {}
      };
      
      
      int main ()
      {
          DerivedClass<C<int>> derived;
      
          return 0;
      }
      

      我的错误假设是因为 C 是从 A 派生的,所以可以使用它。不知道我在哪里阅读/误解了它,但这会浪费很多时间。

      【讨论】:

        【解决方案3】:

        当然,您不会在DerivedClass 中覆盖PrimaryClass 中的DoFunThings。你只是重载它。要覆盖它,它们必须具有相同的签名。您可以在 C++11 中使用 override 关键字轻松检测到此错误。

        template <class T>
        class A
        {
        public:  
            virtual void FunThings ( const A<T> &orig, A<T>* new_one ) = 0;   
            T thing{};
        };
        
        template <class T>
        class C: public A < T >
        {
        public:
            virtual void FunThings ( const C<T> &orig, C<T>* new_one ) {}
        };
        
        template <class T>
        class PrimaryClass
        {
        public:    
            virtual void DoFunThings ( A<T>* d ) = 0;
        };
        
        template<class T>
        class DerivedClass: public PrimaryClass<T>
        {
        public:
            virtual void DoFunThings ( C<T>* d ) override {}
        };
        
        int main ()
        {
            DerivedClass<int> derived;
        }
        

        现在编译器(在我的例子中是 Clang)会发出一个错误:

        test.cpp:27:18: error: 'DoFunThings' marked 'override' but does not override any
              member functions
            virtual void DoFunThings ( C<T>* d ) override {}
        

        【讨论】:

        • 我说我知道覆盖问题,需要一个解决方案来利用 A 的派生。
        猜你喜欢
        • 2011-06-12
        • 2015-02-25
        • 1970-01-01
        • 2021-12-12
        • 1970-01-01
        • 1970-01-01
        • 2010-12-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多