如何在基类构造函数中使用派生类成员 所以,我是一个C++新手,所以让我解释一下我的问题,我是如何理解的,如果我错了请纠正我。

如何在基类构造函数中使用派生类成员 所以,我是一个C++新手,所以让我解释一下我的问题,我是如何理解的,如果我错了请纠正我。,c++,oop,inheritance,C++,Oop,Inheritance,我有一个表示ui按钮的基类。它有onClick、mouseOver等方法和label等成员。此外,它还有一个rect成员,其中的“矩形”数据表示按钮:按钮在窗口中的x和y位置及其宽度和高度 简化代码: #include <cstdio> struct Rect { int x { 0 }; int y { 0 }; int w { 0 }; int h { 0 }; }; class BaseButton { protected: const int w

我有一个表示ui按钮的基类。它有
onClick
mouseOver
等方法和
label
等成员。此外,它还有一个
rect
成员,其中的“矩形”数据表示按钮:按钮在窗口中的x和y位置及其宽度和高度

简化代码:

#include <cstdio> 

struct Rect {
  int x { 0 };
  int y { 0 };
  int w { 0 };
  int h { 0 };
};

class BaseButton {
  protected:
  const int width { 0 };
  const int height { 0 };
  Rect rect;

  public:
  BaseButton(int x, int y) {
    rect = Rect { x, y, width, height };
  }

  void debugRect () {
    printf("x: %d, y: %d, w: %d, h: %d\n", rect.x, rect.y, rect.w, rect.h);
  }
};
如果我调试它,结果如下:

int main () {
  CheckboxButton cbb { 10, 10 };
  cbb.debugRect(); // x: 10, y: 10, w: 0, h: 0
}
与其他一些OOP语言不同的是,基类构造函数无法访问派生类变量。例如,在python中,代码如下所示:

class Rect:
  def __init__(self, x, y, w, h):
    self.x = x
    self.y = y
    self.w = w
    self.h = h

class BaseButton:
  width = 0
  height = 0

  def __init__(self, x, y):
    self.rect = Rect(x, y, self.width, self.height)

  def debug_rect(self):
    print "x: {0}, y: {1}, w: {2}, h: {3}".format(self.rect.x, self.rect.y, self.rect.w, self.rect.h)

class CheckboxButton(BaseButton):
  width = 16
  height = 16

class SendButton(BaseButton):
  width = 32
  height = 16

cbb = CheckboxButton(10, 10)
cbb.debug_rect() # x: 10, y: 10, w: 16, h: 16
class BaseButton {
  Rect rect;

  public:
  BaseButton(int x, int y, int w, int h) {
    rect = Rect { x, y, w, h };
  }

  void debug_rect () {
    printf("x: %d, y: %d, w: %d, h: %d\n", rect.x, rect.y, rect.w, rect.h);
  }
};

class CheckboxButton: public BaseButton {
  private:
  using BaseButton::BaseButton;

  protected:

  public:
  CheckboxButton(int x, int y): BaseButton { x, y, 16, 16 } {};
};

int main () {
  CheckboxButton cbb { 10, 10 };
  cbb.debug_rect();
}
我希望尽可能地重用基类构造函数的代码。因此,基本上,“配置”派生类参数,并让构造函数代码使用它们来生成每种类型按钮的实例

我能想到的一个解决方案是让基类构造函数接受它需要的所有参数,并使用固定参数从派生类重载此类构造函数,如下所示:

class Rect:
  def __init__(self, x, y, w, h):
    self.x = x
    self.y = y
    self.w = w
    self.h = h

class BaseButton:
  width = 0
  height = 0

  def __init__(self, x, y):
    self.rect = Rect(x, y, self.width, self.height)

  def debug_rect(self):
    print "x: {0}, y: {1}, w: {2}, h: {3}".format(self.rect.x, self.rect.y, self.rect.w, self.rect.h)

class CheckboxButton(BaseButton):
  width = 16
  height = 16

class SendButton(BaseButton):
  width = 32
  height = 16

cbb = CheckboxButton(10, 10)
cbb.debug_rect() # x: 10, y: 10, w: 16, h: 16
class BaseButton {
  Rect rect;

  public:
  BaseButton(int x, int y, int w, int h) {
    rect = Rect { x, y, w, h };
  }

  void debug_rect () {
    printf("x: %d, y: %d, w: %d, h: %d\n", rect.x, rect.y, rect.w, rect.h);
  }
};

class CheckboxButton: public BaseButton {
  private:
  using BaseButton::BaseButton;

  protected:

  public:
  CheckboxButton(int x, int y): BaseButton { x, y, 16, 16 } {};
};

int main () {
  CheckboxButton cbb { 10, 10 };
  cbb.debug_rect();
}
我能想到的另一个解决方案是使用模板:

template<int W, int H>
class BaseButton {
  Rect rect;

  public:
  BaseButton(int x, int y) {
    rect = Rect { x, y, W, H };
  }

  void debug_rect () {
    printf("x: %d, y: %d, w: %d, h: %d\n", rect.x, rect.y, rect.w, rect.h);
  }
};

class CheckboxButton: public BaseButton<16, 16> {
  public:
  using BaseButton::BaseButton;
};

int main () {
  CheckboxButton cbb { 10, 10 };
  cbb.debug_rect();
}
模板
类基本按钮{
Rect-Rect;
公众:
基本按钮(整数x,整数y){
rect=rect{x,y,W,H};
}
void debug_rect(){
printf(“x:%d,y:%d,w:%d,h:%d\n”,rect.x,rect.y,rect.w,rect.h);
}
};
类CheckboxButton:公共基本按钮{
公众:
使用BaseButton::BaseButton;
};
int main(){
复选框按钮cbb{10,10};
cbb.debug_rect();
}
这两种解决方案都有效,但我的问题是它们的伸缩性不好。在我的简化示例中,我只是向基类构造函数添加了两个参数,而构造函数只是几行代码。如果配置参数为20,而构造函数比这复杂得多,该怎么办

什么是解决此类问题的标准C++方式?谢谢你解决了这个问题 在子对象中,您尝试在不使用显式构造函数的情况下初始化父对象的成员。在尝试这样做时,您可以在派生类中定义与父类中的成员同名的新成员变量,以便这些变量的名称被隐藏:

class CheckboxButton: public BaseButton {
  protected:
  const int width { 16 };   // new CheckboxButton::width, 
                            //          leaves BaseButton::width unchanged
  const int height { 16 };  // leaves BaseButton::width unchanged
  ...
};
调试函数是在基类中定义的,它只知道
BaseButton::width
BaseButton::height
,这两个常量在0时保持不变

解决方案 一个好的做法是在构造函数中使用mem初始值设定项构造成员变量,因为这些变量用于构造成员:

class BaseButton {
protected:
  const int width;
  const int height;
  Rect rect;

public:
  BaseButton(int x, int y, int w, int h) : width{w}, height{h} {
    rect = Rect { x, y, width, height };
  }
  BaseButton(int x, int y) : BaseButton(x,y,0,0) {}  // delegate construction
                                                     // to other constructor

  ...
};
您可以看到,有一个包含两个参数的短构造函数,它将该构造转换为一个包含四个参数的构造函数,它还允许初始化
height
width
。顺便注意,构造函数体中的语句是在mem初始值设定项之后执行的

然后,派生类将调用相应的基构造函数:

class CheckboxButton: public BaseButton {
public:
  CheckboxButton (int x, int y) : BaseButton(x,y, 16,16) {}
};

如果
width
height
不是常量,则可以像在原始代码中一样,只为基类保留一个构造函数,并在派生构造函数的主体中分配新值。

请查看此列表。你的问题太长,主题太广泛。请尽量缩小范围。为什么不让
BaseButton
构造函数将宽度和高度作为参数呢?然后,您可以使用
CheckboxButton
构造函数初始值设定项列表中的正确参数,创建自己的
CheckboxButton
构造函数“调用”基本构造函数。如果您想获得一些灵感,可以访问。您甚至可以访问源代码(例如on),但我相信API参考对您来说更有趣。顺便说一句,在Qt之前,我使用了gtkmm,在:GTK+,在:OSF/Motif。。。不知何故,它们的工作原理都很相似。:-)因此,您的问题实际上不是关于构造过程中的虚拟调用(这是一个常见问题),而是关于如何处理GUI代码中的大量参数。这就是命名参数的习惯用法。这也是一个常见问题。@Someprogrammerdude这是我在问题中展示的第一个解决方案。正如我在问题的最后一部分中所说,当你没有两个参数(宽度和高度)而是10或20时,问题就会出现。