使用 C 风格变量传递双精度值时出现意外的类型转换

问题描述 投票:0回答:1

我尝试了变量 Args。 Matrix 类与 int 一起使用,但是当我使用 double 时,当我不转换它时,我得到了错误的 23 值。我读到其他类型会自动转换

  • float 参数被转换为 double,如浮点提升中那样
  • bool、char、short 和无范围枚举被转换为 int 或更宽的整数类型,如整数提升中一样”我不明白为什么我得到错误的值。
#include "matrix.h"
//#include "coordinate_sys.h"

int main(){

//Coordinate_3d<double>Coordinate_3(1,2,3);
//Coordinate_3.print_console();

Matrix<double>sick_matrix(2,2,4,20.5,(double)23,23,0);
sick_matrix.print_console();

while(1){}

return 0;
}
#ifndef MATRIX_H
#define MATRIX_H
#include <iostream>
#include <cstdarg>

template<typename T>
class Matrix{
private:
    T * arr_ptr;
    unsigned int rows;
    unsigned int cols;
    
public:
    Matrix(unsigned int rows, unsigned int cols, unsigned int args_ctr,...): rows(rows),cols(cols){
        //react to false input
        //--------------------------------------------------------------------------------------------
        if(cols * rows < args_ctr){ //to many args
            std::cout << "Matrix initilization with to many arguments" << std::endl;
            exit(EXIT_FAILURE);
        }
        //--------------------------------------------------------------------------------------------
        
        arr_ptr = new T[rows*cols];
        va_list args;
        unsigned int fill_var = 0;
        va_start(args,args_ctr);

        while (fill_var < args_ctr)
        {
            arr_ptr[fill_var] = va_arg(args,T);
            fill_var++;
        }
        
        va_end(args);   
    }

    void print_console(){for(unsigned int i = 0; i < rows*cols; i++){std::cout << arr_ptr[i] << std::endl;}}

};

#endif

我将使用变量模板参数来执行此操作,但为什么转换中会出现错误?

c++ class templates variadic-functions ellipsis
1个回答
0
投票

问题是 C 风格的可变参数绝对不提供类型安全。

(double)23,23,0
传递一个
double
和两个
int
,并且您期望构造函数中存在三个
double

您通常应该远离 C++ 中的 C 风格变量。

解决方案A -
std::initializer_list

Matrix(unsigned int rows, unsigned int cols, std::initializer_list<T> args)
  : rows(rows), cols(cols) {
    // args.size() can be used to obtain the number of arguments
}

解决方案 B - 静态大小的矩阵

在几乎所有情况下,无论如何,您都在编译时知道矩阵的大小。如果将行和列转换为非类型模板参数,很多问题都变得微不足道:

template <typename T, std::size_t Rows, std::size_t Columns = Rows>
class Matrix {
  private:
    // ...
  public:
    T data[Rows * Columns];
};

你甚至不再需要构造函数,并且可以写:

using Mat3f = Matrix<float, 3>; // convenience alias

Mat3f mat{/* ... */}; // aggregate initialization, no constructor needed

如果您坚持拥有一个构造函数,它可以是一个仅采用一个类型为

std::initializer_list<T>
的参数的构造函数,并且您仍然可以使用语法
Mat3f{...}

© www.soinside.com 2019 - 2024. All rights reserved.