在所有未来的派生类中,在抽象类构造方中执行初始化行为
我从 Qt 库中的现有输入字段类派生(不必熟悉它),在其中添加一个文本验证器来检查有效输入(使用 QLineEdit 验证选项)和一些进一步的功能/覆盖。
为此,我创建了一个名为 ConstrainedQLineEdit
的纯虚拟类,它派生自 QLineEdit
,然后我从中实现特定的输入字段(例如 PasswordQLineEdit
)。这是我的实现的简化:
抽象基类:
class ConstrainedQLineEdit : public QLineEdit
{
Q_OBJECT // QT macro that implements observer pattern with signals/slots among others (not relevant)
public:
virtual ~ConstrainedQLineEdit()
{
// delete validator;
}
protected:
ConstrainedQLineEdit(QWidget* parent = nullptr)
: QLineEdit(parent) // , validator(nullptr)
{
_initialize();
}
virtual void _initialize()
{
QString validatorInformation = _getValidatorInformation();
// validator = new Validator{validatorInformation};
// further logic
}
virtual QString _getValidatorInformation() const = 0;
// Validator validator;
// Further variables and necessary overrides of QLineEdit
};
密码的派生类
class PasswordQLineEdit : public ConstrainedQLineEdit
{
Q_OBJECT // idem
public:
PasswordQLineEdit(QWidget* parent = nullptr)
: ConstrainedQLineEdit(parent)
{}
virtual ~PasswordQLineEdit() = default;
protected:
QString _getValidatorInformation() const override
{
QString validatorInformation;
// logic generating the information
return validatorInformation;
}
};
可执行文件
int main(int argc, char** argv)
{
QApplication application(argc, argv);
PasswordQLineEdit passwordQLineEdit;
passwordQLineEdit.show();
return application.exec();
}
执行后,我得到以下内容错误(没有调试器,应用程序会崩溃分段错误样式):
pure virtual method called
terminate called without an active exception
我的问题:
我知道从基类构造函数调用虚函数是不受欢迎的,因为它可能会导致这种情况的问题。我也知道我可以将初始化放在派生类构造函数中。
但是,这是一个基类,我的团队将来将使用它来创建更多自定义字段,并且我想专门强制(或预定义)派生类的构造方式,以便其他团队成员实际上只具有定义一个传递相同参数的构造函数,然后通过 QString _getValidationInformation() 覆盖验证逻辑并完成它。
有什么设计建议可以在不破坏类结构的情况下实现此目的(我正在重写 QLineEdit 的更多虚拟函数并且还有其他逻辑)?
I'm deriving from an existing input field class from the Qt Library (not necessary to be familiar with it), where I'm adding a text validator that checks for valid inputs (using the QLineEdit validation options) and some further functionalities/overrides.
For this I create a pure virtual class called ConstrainedQLineEdit
which derives from QLineEdit
, from which then I implement specific input fields (e.g. PasswordQLineEdit
). Here a simplification of my implementation:
Abstract Base class:
class ConstrainedQLineEdit : public QLineEdit
{
Q_OBJECT // QT macro that implements observer pattern with signals/slots among others (not relevant)
public:
virtual ~ConstrainedQLineEdit()
{
// delete validator;
}
protected:
ConstrainedQLineEdit(QWidget* parent = nullptr)
: QLineEdit(parent) // , validator(nullptr)
{
_initialize();
}
virtual void _initialize()
{
QString validatorInformation = _getValidatorInformation();
// validator = new Validator{validatorInformation};
// further logic
}
virtual QString _getValidatorInformation() const = 0;
// Validator validator;
// Further variables and necessary overrides of QLineEdit
};
Derived class for passwords
class PasswordQLineEdit : public ConstrainedQLineEdit
{
Q_OBJECT // idem
public:
PasswordQLineEdit(QWidget* parent = nullptr)
: ConstrainedQLineEdit(parent)
{}
virtual ~PasswordQLineEdit() = default;
protected:
QString _getValidatorInformation() const override
{
QString validatorInformation;
// logic generating the information
return validatorInformation;
}
};
Executable
int main(int argc, char** argv)
{
QApplication application(argc, argv);
PasswordQLineEdit passwordQLineEdit;
passwordQLineEdit.show();
return application.exec();
}
Upon executing I get the following error (without debugger the application crashes segmentation-fault style):
pure virtual method called
terminate called without an active exception
My question:
I'm aware that it is frowned upon to call a virtual function from the base class constructor since it can lead to exactly this kind of problems. I'm also aware I could just put the initialization in the derived-class constructor.
However, this is a base class that my team will use in the future to create further custom fields, and I want to specifically enforce (or pre-define) the behaviour of how derived classes are constructed so that other team-members really only have to define a constructor that passes the same arguments and then the validation logic via QString _getValidationInformation() override
and be done with it.
Any design recommendations to achieve this without breaking the class structure (I'm overriding further virtual functions of QLineEdit
and there's additional logic)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
不仅是“皱眉”,而且是错误的。编写这样的代码将导致错误。您的错误来自以下事实:在施工过程中,您的子类虚拟方法从未被调用,只有调用基类方法。因此,它试图从基类调用
_getValidatorInformation()
,但尚未实现,因此错误。如果您提供了默认实现,则编译器不会说什么,并且您将拥有广告错误的代码。我建议使用工厂功能来创建对象。工厂功能将负责
一些伪代码以显示这个想法:
It is not only "frowned upon", it is wrong. Writing such code will lead to bugs. Your error comes from the fact that your child class virtual method is never called, in the construction process, only the base class methods are called. Hence, it tries to call the
_getValidatorInformation()
from the base class, but it has not been implemented, hence the error. If you had provided a default implementation, then the compiler would have said nothing and you would have ad bugged code.What I would suggest is to use a factory function to create your object. The factory function would be responsible to
Some pseudo code to show the idea: