【问题标题】:Can you rename members when using typedef?使用 typedef 时可以重命名成员吗?
【发布时间】:2014-04-26 15:59:38
【问题描述】:

我使用三个floats 的结构来表示平移和缩放,如下所示:

typedef struct Translation{
    Translation() : x(0.0), y(0.0), z(0.0){};
    Translation(x, y, z) : x(x), y(y), z(z){};
    //some arithmetic operators
    float x, y, z;
}
Translation;

typedef Translation Scale;

现在我也想用这个定义来表示旋转,但我不想访问他们的成员为xyz,而是yawpitch 和@ 987654328@。是否可以通过typedef 重命名这样的成员?还是有另一种方法不包括重新定义完整的结构及其成员?

【问题讨论】:

  • 没有。 typedef 用于类型。 xyz 不是类型。
  • 不要这样做。 TranslationScaleRotation 都是不同的概念。它们都包含三个floats 的事实是偶然的,并不是在它们之间共享代码的好理由。 typedef 不会将一个类型复制到另一个类型,它只会创建一个别名。因此,您可以将 Rotation 传递给期望 Scale 的函数,因为它们只是同一类型的两个名称,这将颠覆所有类型安全的概念。
  • @Oktalist 非常好!我曾考虑过继承,但这引发了同样的问题。我想我应该分别定义这三个。
  • 你为什么这么懒而不只是复制'n'paster代码,搜索替换?似乎需要几分钟的工作。
  • @EdHeal 因为一旦我更改了某个类的某些内容,这些更改就不会反映在其他类中。此外,这意味着可能会避免大量冗余代码。

标签: c++ struct typedef member


【解决方案1】:

不,因为 typedef 用于类型(例如 int、double 等)。

最清楚的方法是制作另一个结构。

编辑: 由于这是 C++,我建议您创建一个包含所有逻辑并从中派生的基类。换句话说,使用继承

例子:

#include <iostream>

class Base {
 public:
  Base(int aa, int bb, int cc)
   : a(aa), b(bb),c(cc) {}

  int getA() {
    return a;
  }

  int getB() {
    return b;
  }

  int getC() {
    return c;
  }

  // Notice that you make the data members private,
  // but then you will need the getters to access them
  // in the derived classes
 protected:
  int a;
  int b;
  int c;
};

class A : public Base {
 public:
  A(int aa, int bb, int cc)
   : Base(aa, bb, cc) {}

  int x() {
    return a;
  }

  int y() {
    return b;
  }

  int z() {
    return c;
  }
};

class B : public Base {
 public:
  B(int aa, int bb, int cc)
   : Base(aa, bb, cc) {}

  int gama() {
    return a;
  }

  int beta() {
    return b;
  }

  int theta() {
    return c;
  }
};

int main() {
  A a_object(1, 2, 3);

  B b_object(4, 5, 6);

  std::cout << "a of a_object = " << a_object.x() << "\n";
  std::cout << "b of b_object = " << b_object.gama() << "\n";

  return 0;
}

【讨论】:

  • 您对typedef 的看法是正确的,但我正在寻找一种避免重新输入所有内容的方法。这三个结构的工作方式完全相同,即使它们的算术和赋值运算符也是如此。
  • @iFreilicht,您在我更新时发布了您的答案。请注意,使用我的方法,您可以更轻松地扩展和维护您的代码。 :)
  • 我真的不希望三个类之间有任何互操作性,这就是我避免它的原因。另外,我喜欢scale.x = 1 的简单性,而不是scale.setX(1)。但是,是的,宏可能不是最容易维护的方式。另请注意,不必在代码中使用aaFoo(int a) : a(a){}; 之类的构造函数是 C++ 中 100% 定义的行为。 (如果我正确理解了文档)
  • 你可以拥有 .x,让数据成员公开,但没关系。我不确定你说的构造函数。
  • 我认为您对构造函数是正确的。但是,在正文中包含参数可能会导致错误。感谢您通知我。
【解决方案2】:

所以这是我的继续:它可能并不完美,但允许同时轻松修改所有三个 structs,同时保留所有三种类型的清晰分离,这对于 @Oktalist 来说非常重要指出。 这三种类型之间应该没有互操作性,因此不能选择继承和typedef

所以,我在宏中找到了解脱:

#define THREE_FLOAT_STRUCT(NAME, X, Y, Z, X_STANDARD, Y_STANDARD, Z_STANDARD) typedef struct NAME{\
    NAME() : X(X_STANDARD), Y(Y_STANDARD), Z(Z_STANDARD){};\
    NAME(float X, float Y, float Z) : X(X), Y(Y), Z(Z){};\
    NAME operator+(const NAME& other) const{ return NAME(X + other.X, Y + other.Y, Z + other.Z); }\
    NAME operator-(const NAME& other) const{ return NAME(X - other.X, Y - other.Y, Z - other.Z); }\
    NAME operator*(float divisor) const{ return NAME(X * divisor, Y * divisor, Z * divisor); }\
    NAME operator/(float divisor) const{ return NAME(X / divisor, Y / divisor, Z / divisor); }\
    NAME& operator+=(const NAME& other){ X += other.X; Y += other.Y; Z += other.Z; return *this; }\
    NAME& operator-=(const NAME& other){ X -= other.X; Y -= other.Y; Z -= other.Z; return *this; }\
    NAME& operator*=(float divisor){ X *= divisor; Y *= divisor; Z *= divisor; return *this; }\
    NAME& operator/=(float factor){ X /= factor; Y /= factor; Z /= factor; return *this; }\
    float X, Y, Z;\
} NAME;

THREE_FLOAT_STRUCT(Rotation, roll, pitch, yaw, 0.0, 0.0, 0.0)
THREE_FLOAT_STRUCT(Translation, x, y, z, 0.0, 0.0, 0.0)
THREE_FLOAT_STRUCT(Scale, x, y, z, 1.0, 1.0, 1.0)

我个人喜欢这种解决方案。确实有点难读,但我们只是在谈论基本的算术运算,代码并没有什么花哨的东西,你一眼就能看出定义了哪些运算符。

如果您有更好的解决方案,请随时将它们作为另一个答案发布。

【讨论】:

  • ...然后再写一些难以理解和维护的代码
  • 天哪,请说您实际上并没有使用它。 :(
  • 不要这样做。您正在降低可维护性和可理解性,没有真正的好处。如果你想在 OOP 中使用不同的方法名,你可以继承
  • @tenfour 我今天感觉很疯狂......所以是的,我做到了。但我知道这是错的。至少它可能会赢得代码高尔夫球奖。
  • @dkackman 是的,我马上就体验到了。不过,尝试它绝对很有趣,我为它按预期的方式工作而感到自豪。 (这本身已经表明这是一个坏主意。)我现在要继承。
猜你喜欢
  • 1970-01-01
  • 2010-11-16
  • 1970-01-01
  • 1970-01-01
  • 2020-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-12
相关资源
最近更新 更多