C++ c+中的静态公共值函数+;
假设我们有Matrix4类(矩阵四乘四) 此类的用户通常希望使用标识矩阵初始化Matrix4类型的变量 我知道有两种选择:C++ c+中的静态公共值函数+;,c++,c++11,C++,C++11,假设我们有Matrix4类(矩阵四乘四) 此类的用户通常希望使用标识矩阵初始化Matrix4类型的变量 我知道有两种选择: 为更改*this值的类提供成员函数SetAsIdentity。所以用户会这样做: Mat4 m; m.SetAsIdentity(); 提供返回静态常量标识矩阵的静态成员(或非成员)函数,类似于以下内容(请参见更新): 然后像这样使用它: Mat4 m = Mat4::Identity(); 在我看来,我希望使用2多于1,因为它可以在一行代码中使用。 是否有更好的方
Mat4 m;
m.SetAsIdentity();
Mat4 m = Mat4::Identity();
- 默认值为默认值
- 必须能够定义非默认ctor(2实际上不符合此要求。它在msvc上编译,但在gcc或clang上编译)
class Mat4
{
public:
struct SIdentity {};
float f[16];
Mat4() = default;
Mat4(SIdentity) : f{ 1, 0, 0, 0 , 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}
{}
};
并对其进行初始化:
Mat4 m(Mat4::SIdentity{});
哪一个看起来更优雅(尽管它需要笨拙的实例化,变量会被优化掉吗?)
更新2:
geza的一条评论建议将SIdentity作为constexpr。这增加了能够进行(静态)常量初始化和编译时初始化/构造的好处如果您不关心您的
矩阵
在默认情况下将被初始化为标识矩阵,那么您可以简单地编写如下内容(简化的数据结构)。在这里,每个矩阵pod
首先将是一个单位矩阵,直到您将值更改为其他值或添加覆盖x
初始值的其他构造函数:
struct MatrixPOD {
public:
int x[4] = { 0,0,0,1 };
MatrixPOD() { };
};
MatrixPOD gi; // identity matrix, even at file scope
如果您可以使用普通数据结构,还可以提供用于初始化的宏,例如:
struct MatrixPOD2 {
public:
int x[4];
#define IDENTITY { 0,0,0,1 }
};
MatrixPOD2 gi2 = IDENTITY;
但是,如果您想拥有一个包含更多构造函数的类,并且只想在显式声明时具有“预初始化”,则可以引入一个全局标识实例,然后使用该实例初始化其他矩阵对象。请参阅以下代码,其中使用私有构造函数初始化此全局标识实例:
struct Matrix {
public:
int x[4];
Matrix() = default;
const static Matrix identity;
private:
Matrix(bool identity) {
if (identity)
memcpy (x,x_identity,sizeof(x));
};
const static int x_identity[4];
};
const Matrix Matrix::identity(true);
const int Matrix::x_identity[4] = { 0,0,0,1 };
int main() {
MatrixPOD p; // always an identity matrix
Matrix m; // not an identity matrix
Matrix mi = Matrix::identity; // identity matrix since explicitly assigned
return 0;
}
如果您不关心您的
矩阵
在默认情况下会被初始化为标识矩阵,那么您可以简单地编写如下内容(简化的数据结构)。在这里,每个矩阵pod
首先将是一个单位矩阵,直到您将值更改为其他值或添加覆盖x
初始值的其他构造函数:
struct MatrixPOD {
public:
int x[4] = { 0,0,0,1 };
MatrixPOD() { };
};
MatrixPOD gi; // identity matrix, even at file scope
如果您可以使用普通数据结构,还可以提供用于初始化的宏,例如:
struct MatrixPOD2 {
public:
int x[4];
#define IDENTITY { 0,0,0,1 }
};
MatrixPOD2 gi2 = IDENTITY;
但是,如果您想拥有一个包含更多构造函数的类,并且只想在显式声明时具有“预初始化”,则可以引入一个全局标识实例,然后使用该实例初始化其他矩阵对象。请参阅以下代码,其中使用私有构造函数初始化此全局标识实例:
struct Matrix {
public:
int x[4];
Matrix() = default;
const static Matrix identity;
private:
Matrix(bool identity) {
if (identity)
memcpy (x,x_identity,sizeof(x));
};
const static int x_identity[4];
};
const Matrix Matrix::identity(true);
const int Matrix::x_identity[4] = { 0,0,0,1 };
int main() {
MatrixPOD p; // always an identity matrix
Matrix m; // not an identity matrix
Matrix mi = Matrix::identity; // identity matrix since explicitly assigned
return 0;
}
你的问题的答案是没有理由使用到目前为止介绍的任何技术
constexpr
。因此,对于constexpr可构造类型来说,这仍然是一个糟糕的选择。另一种方法是使用constexpr静态全局变量#include <array>
#include <type_traits>
struct MatrixFour {
MatrixFour() = default;
constexpr MatrixFour(const std::array<double, 16> x) : m_data(x) {}
static constexpr MatrixFour makeIdentity() {
return MatrixFour({1,0,0,0,
0,1,0,0,
0,0,1,0,
0,0,0,1});
}
private:
std::array<double, 16> m_data;
};
int main() {
static_assert(std::is_pod<MatrixFour>::value, "");
constexpr auto x = MatrixFour::makeIdentity();
return 0;
}
#包括
#包括
结构矩阵四{
MatrixFour()=默认值;
constexpr MatrixFour(const std::array x):m_data(x){}
静态constexpr矩阵四个makeIdentity(){
返回矩阵四({1,0,0,0,
0,1,0,0,
0,0,1,0,
0,0,0,1});
}
私人:
std::数组m_数据;
};
int main(){
静态断言(std::is_pod::value,“”);
constexpr auto x=MatrixFour::makeIdentity();
返回0;
}
您的问题的答案是,没有理由使用目前介绍的任何技术
constexpr
。因此,对于constexpr可构造类型来说,这仍然是一个糟糕的选择。另一种方法是使用constexpr静态全局变量#include <array>
#include <type_traits>
struct MatrixFour {
MatrixFour() = default;
constexpr MatrixFour(const std::array<double, 16> x) : m_data(x) {}
static constexpr MatrixFour makeIdentity() {
return MatrixFour({1,0,0,0,
0,1,0,0,
0,0,1,0,
0,0,0,1});
}
private:
std::array<double, 16> m_data;
};
int main() {
static_assert(std::is_pod<MatrixFour>::value, "");
constexpr auto x = MatrixFour::makeIdentity();
return 0;
}
#包括
#包括
结构矩阵四{
MatrixFour()=默认值;
constexpr MatrixFour(const std::array x):m_data(x){}