【问题标题】:How can I override the member of (->) operator of a base class如何覆盖基类的 (->) 运算符的成员
【发布时间】:2015-06-15 15:16:57
【问题描述】:

背景:我有 Qt 生成的没有共同祖先的 UI 类。我正在对使用这些 UI 类之一的类(例如“Door”)进行子类化,而派生类(“OakDoor”)将使用不同的 UI 类,尽管许多 UI 元素将具有相同的名称。

到目前为止,我一直在隐藏 UI 基类(即派生类使用不同类型但名称相同的 UI 类),但现在需要依靠继承来处理基类确实适用于 UI 类的情况;在这种情况下,隐藏不起作用。

我已经询问了一种使用继承的方法,并指出了使用组合的方向。所以我试图找到一种有效的方法来做到这一点,而不必为每个 UI 元素定义访问函数。这不是真正的作曲,但我认为它让我不费吹灰之力。

class form_container 
{
public:
  form_container(){};
  form_container(Ui_A_Form * form){_form = form;}
  ~form_container(){ delete _form; }  
  Ui_A_Form *_form;
  Ui_A_Form & operator->()
  {
    return *_form;
  }
};

当时的想法是让 Door 使用这个类,而 OakDoor 是它的子类:

class B_form_container : public form_container
{
public:
  B_form_container(Ui_B_Form * form){_form=form;}
  ~B_form_container(){delete _form;}  
  Ui_B_Form  *_form;
  Ui_B_Form & operator->()
  {
    return *_form;
  }
};

所以我真的只是在转移隐藏。无论如何,问题似乎与我重载运算符->()有关。 在我的门课上,我有 form_container *_myform; 这样构造的:

_myform = new form_container(new A_Form());

但是当我尝试访问 A_Form 中的任何内容时,它不会编译,例如 Qt SetupUI 函数:

_myform->setupUi(_a_widget);

我显然做错了什么。非常感谢那里的任何帮助 - 非常感谢! (当子类尝试删除基类中的 _form 时,我会看到问题,但我稍后会解决)

编辑:好的,现在正在编译(非常感谢@(R Sahu)),但我没有看到我期望的重载。例如:

class base_class()
{
   form_container *_myform;
};

class derived_class(): public base_class()
{
 //inherit _myform;
};

//(constructor for derived class)
derived_class()::derived_class()
{
  _myform = new B_form_container(new B_form());
  (*_myform)->setupUI(new QWidget());  // tries to setupUi on an A_form
}

这是调用 form_container::operator->(),大概是因为它不是虚拟的。如果我在基类 form_container 中将其设为虚拟,则派生类 B_form_container 会抱怨该函数仅因返回类型而异。 有没有解决的办法? 例如,我可以做这样的事情吗:

class base : public A_form
{
 virtual base * operator->()
 {
    // not sure how to return ->() operator of A_form
    return A_form::operator->(); // ???
 }
};

class derived : public base, public B_form
{
 virtual base *operator->()
 {
   return B_form::operator->(); // again??? 
 }
} ;

另一个编辑:我认为我想做的事情已经不可能了。如果你能纠正我,请做。与此同时,我要编写一些东西来处理 moc 输出并创建具有我可以覆盖的访问函数的类。

【问题讨论】:

  • 似乎你尝试的越多,它就越没有意义......如果derived源自base,那么它间接源自A_form。因此派生出A_formB_form

标签: c++ qt inheritance overloading operator-keyword


【解决方案1】:
_myform = new form_container(new A_Form());
_myform->setupUi(_a_widget);

不是用于访问operator->() 函数的正确语法。使用该语法,编译器期望类form_container 中有一个成员函数setupUi()。正确的语法是:

_myform = new form_container(new A_Form());
(*_myform)->setupUi(_a_widget);
// This translates to:
// Invoke the operator->() function on (*_myform)
// Use the return value of the function and call `setupUi()` on the returned pointer.

_myform = form_container(new A_Form());
_myform->setupUi(_a_widget);

另外,函数需要返回一个指针,而不是一个引用。

Ui_B_Form* operator->()
{
  return _form;
}

【讨论】:

  • 感谢清理参考的东西,这是我原来的。如果我使用您的第一次更正(_myform 是 form_container*),它会编译。你能解释一下为什么我需要取消引用 _myform 才能使用运算符吗?
  • 对不起,我不得不取消回答这个问题。事实证明,虽然这可以编译,但我没有得到我预期的行为。见上面的编辑
【解决方案2】:

正如我最终意识到的那样,这是不可能的。运算符 ->() 必须返回它所作用的类型,因此它不能用作虚函数。

【讨论】:

  • “真正的”虚函数也不适用于此。这些也需要具有相同的签名。当然,您可以为两个 UI_?_Form 类提供一个具有相关虚函数的公共基础,并通过对该基础的引用/指针以多态方式访问它们(从而保留签名)。
  • 这正是我所做的。我最终编写了一个小实用程序来获取 .ui 文件并自动编写具有虚函数的基类。我在编译 .ui 文件时将此称为构建步骤,因此一旦设置好,它就非常方便。
  • 酷!是的,多态性真的很酷。结合模板,我不确定是否有任何其他语言能够让我有这么大的能力来创建模板类型的复杂意大利面条但是给它们一个通用的基本接口。第二个想法,也许我不应该有这么大的权力。 :D
  • 将自己的答案标记为答案是不公平的……更何况这不是真正的解决方案。
  • 完全可以回答您自己的问题,在这种情况下,解决方案是无法执行我正在寻找的操作,并且在下面的 cmets 中我解释了我的解决方法。跨度>
猜你喜欢
  • 2019-12-06
  • 1970-01-01
  • 2012-07-09
  • 2014-01-02
  • 1970-01-01
  • 2011-08-15
相关资源
最近更新 更多