代码之家  ›  专栏  ›  技术社区  ›  terpak

C++:如何将对象作为模板的基类传递给函数

  •  0
  • terpak  · 技术社区  · 7 年前

    我想编写一个类,以便在类声明中定义它的模板类型(即 class AChar : public A<char> ),然后可以将派生类传递到接受父类的函数中,就像我对非模板化父类所做的那样。是有办法做到这一点,还是有办法达到同样的效果?

    #include <iostream>
    
    template <class T>
    struct A
    {
      T value;
      A(T t) : value(t) {};
      virtual void say() const = 0;
    };
    
    struct AChar : public A<char>
    {
      AChar(char c) : A(c) {};
      void say() const
      {
        std::cout << "A char: " << this->value << std::endl;
      }
    };
    
    struct ABool : public A<bool>
    {
      ABool(bool b) : A(b) {};
      void say() const
      {
        std::cout << "A bool: " << this->value << std::endl;
      }
    };
    
    void makeSay(A a)
    {
      a.say();
    }
    
    int main()
    {
      AChar aChar('g');
      ABool aBool(true);
    
      makeSay(aChar); // A char: g
      makeSay(aBool); // A bool: 1
    }
    

    我想为数据类型的二进制表示编写一个类。为此,我有一个类数据类型,它由各种数据类型类(如IntType、BoolType、ShortType等)扩展,如下所示。我希望能够将这些派生类传递到一个函数中,该函数可以在二进制级别上处理这些类型中的任何一种。我在下面发布了头文件:

    数据类型.h

    #ifndef _DATATYPE_H_
    #define _DATATYPE_H_
    
    #include <cstddef>
    
    template<class T>
    class DataType
    {
    public:
      std::size_t sizeOf() const;
      virtual void toBytes(const T&, char*) const = 0;
      virtual T fromBytes(char*) const = 0;
      virtual T zero() const = 0;
    };
    
    #endif
    

    按类型h

    #ifndef _BYTETYPE_H_
    #define _BYTETYPE_H_
    
    #include "numerictype.h"
    
    class ByteType : public NumericType<char>
    {
    public:
      ByteType();
      void toBytes(char, char[1]) const;
      char fromBytes(char[1]) const;
      char zero() const;
    };
    
    #endif
    

    图表类型.h

    #ifndef _CHARTYPE_H_
    #define _CHARTYPE_H_
    
    #include <cstddef>
    #include <string>
    #include "datatype.h"
    
    class CharType : public DataType<std::string>
    {
      std::size_t length;
    public:
      static const char PADDING = ' ';
    
      CharType();
      CharType(size_t);
      std::size_t getLength() const;
      std::size_t sizeOf() const;
      void toBytes(const std::string&, char*) const;
      std::string fromBytes(char*) const;
      std::string zero() const;
    };
    
    #endif
    

    示例使用

    void writeToFile(DataType d)
    {
      // ...
    }
    
    int main()
    {
      CharType c(1);
      ByteType b;
    
      writeToFile(c);
      writeToFile(b);
    }
    
    1 回复  |  直到 7 年前
        1
  •  1
  •   Remy Lebeau    7 年前

    由于基类是模板化的,因此要向其传递多个派生类型的函数必须:

    1. 本身是模板化的,以便接受基类(必须通过引用或指针传递基类以避免 slicing ).

      template<class T>
      void makeSay(const A<T> &a)
      {
          a.say();
      }
      

      template<class T>
      void writeToFile(const DataType<T> &d)
      {
          // ...
      }
      
    2. 为每个特定派生类型重载(哪种类型不符合使用模板的目的):

      void makeSay(const AChar &a)
      { 
          a.say();
      }
      
      void makeSay(const ABool &a)
      { 
          a.say();
      }
      

      void writeToFile(const ByteType &t)
      {
          // ...
      }
      
      void writeToFile(const CharType &t)
      {
          // ...
      }