C++ 在编译时使用未知类型的对象初始化

C++ 在编译时使用未知类型的对象初始化,c++,auto,C++,Auto,我相信这个问题在这里已经被讨论过很多次了,但是我真的找不到我遇到的问题的答案。我有一个类需要在里面保存一个数组。但是该数组的类型是可靠的(确切地说,它取决于打开的wave文件的比特率,例如8位字符、16位短字符等)。我需要在一个类方法中定义它 我的想法是使用auto关键字声明指针: class WaveReader { // auto *data; }; 然后,在方法内部: void some_func(int datasize) { // case 8: d

我相信这个问题在这里已经被讨论过很多次了,但是我真的找不到我遇到的问题的答案。我有一个类需要在里面保存一个数组。但是该数组的类型是可靠的(确切地说,它取决于打开的wave文件的比特率,例如8位字符、16位短字符等)。我需要在一个类方法中定义它

我的想法是使用
auto
关键字声明指针:

class WaveReader {

//

auto *data;

};
然后,在方法内部:

void some_func(int datasize)
{
    //
    case 8:
      data = new char[datasize];
      break;
    case 16:
      data = new short[datasize];
      break;
    //
    etc.
}
但那是个愚蠢的想法。我知道最简单的方法是为每种类型声明数组,但我想知道是否有一种聪明的方法,也许可以使用一些模板?
非常感谢您的帮助。

多种数据类型。可以使用相同的名称创建单独的重载函数。根据传递的数据类型,它将使用正确的函数。
然后,该函数可以从中调用正确的类。

关键字
auto
不是为此而设计的,将数据声明为:

void* data;
然后,您可以只使用int或enum来跟踪数据类型。比如,

typedef enum 
{
    CHAR,
    SHORT
} DataTypeEnum;
...
DataTypeEnum dataType;
...
并按如下方式修改您的代码:

void some_func(int datasize)
{
    //
    case 8:
      data = static_cast<void*>(new char[datasize]);
      dataType = CHAR;
      break;
    case 16:
      data = static_cast<void*>(new short[datasize]);
      dataType = SHORT;
      break;
    //
    etc.
}
...
if( dataType == CHAR )
{
    ...
}
else if ( dataType == SHORT )
{
    ...
}
void some_func(int datasize)
{
//
案例8:
数据=静态_转换(新字符[数据大小]);
数据类型=字符;
打破
案例16:
数据=静态(新短[数据大小]);
数据类型=短;
打破
//
等
}
...
if(数据类型==CHAR)
{
...
}
else if(数据类型==SHORT)
{
...
}

您可能想想想“这是什么意思”。是的,有些情况下,这种类型的东西(例如,由jsidhu解决)正是您想要和需要的。但它常常表明你试图做一些“不太正确的方式”

一种替代方法是使用虚拟函数:

class Base
{
   public: 
    virtual void do_stuff_with_data() = 0;
}

class CharData
{
  private:
    char * data;

  public:
    CharData(size_t size) { data = new char[size]; }

    void do_stuff_with_data() { ... }; 
};

class ShortData
{
  private:
    short* data;

  public:
    ShortData(size_t size) { data = new short[size]; }
    void do_stuff_with_data() { ... }; 
};

void some_func(int datasize)
{
    Base *pBase;
    case 8:
      pBase = new CharData(datasize);
      break;
    case 16:
      pBase = new ShortData(datasize);
      break;
    //
    etc.

    pBase->do_stuff_with_data(); 
}

我会利用工会来完成这项工作:

union {
    int8_t *i8;
    int16_t *i16;
    /* ... */
} data;

// snip

switch (bitsPerSample) {
case 8:
     dataType = CHAR;
     break;
case 16:
     dataType = SHORT;
     break;
default:
     // throw
}

data.i8 = new int8_t[datasize * bitsPerSample / CHAR_BIT];

do_8bit(data.i8);
// or
do_16bit(data.i16);

delete[] data.i8;
因为您只存储POD,所以如果您分配N*2
char
s或N
short
s,并且您可以使用正确的指针类型而无需强制转换,这并不重要


另外:整数类型来自
,因为在“基本”整数类型的绝对大小上没有garantuee。

谢谢,我正要问铸造的问题。这就解决了问题。类似这样:
delete[]static\u cast(data)
实际上,应该只需要做:delete[]data;delete将计算出其余的。问题是wave文件中的样本是8、16、24位等,当它们是8时,它们是无符号的,其余的是有符号的。当我读取文件时,我需要将样本存储在适当的阵列中,否则它们将无法通过音频库正确播放。您的解决方案看起来不错,但这比仅声明不同类型向量的代码要多10倍。没有简单的方法可以解决这个问题吗?不过Jsidhu解决方案似乎不安全(我会遇到随机崩溃),因此上述解决方案中的原理对于存储音频样本非常有效。很久以前,我在Python中实现了一些非常类似的东西,当我使用Symbian的图形时,上述类型的解决方案用于存储/检索像素。显然,您可能希望在基础中使用一些“通用”功能,并且仅使用派生函数来计算数据的大小,我不认为随机崩溃是因为jsidhu的解决方案本身就不好。它只是没有我的解决方案那么封装,这意味着每当你需要知道“我的数据现在有多大”时,你必须编写大量额外的代码。对不起,崩溃是由我的错误造成的。你是对的,当我思考时,你的解决方案变得越来越有意义。我会牢记在心,看看哪个最适合我。谢谢