Hi, I’m currently using Sonarqube v 8.9.7 and I’m not so satisfied with the cpp:S3230 rule “Do not use the constructor’s initializer list for data member “xy”. Use the in-class initializer instead.”
In general I like in-class initializers of course, but there should be exceptions.
A prominent example is the scaffold code that is created for Qt Widget classes:
mydialog.h
#pragma once
#include <QDialog>
namespace Ui {
class MyDialog;
}
class MyDialog: public QDialog {
Q_OBJECT
public:
explicit MyDialog( QWidget* parent = 0 );
~MyDialog();
private:
Ui::MyDialog* ui;
};
and the implementation would look like this:
#include "mydialog.h"
#include "ui_mydialog.h"
MyDialog::MyDialog( QWidget* parent ) : QDialog( parent ), ui( new Ui::MyDialog) {
ui->setupUi( this );
}
MyDialog::~MyDialog() {
delete ui;
}
The ui member has a forward declared type that is defined in ui_mydialog.h. This is a common insulation technique to avoid dependencies between headers. It leaves all the details of the dialog layout outside of the header and I don’t need to recompile components that use the dialog on every layout change. The ui member cannot be initialized in-class easily (One could do in-class initialization from e.g. a static method, but usually we initialize them by calling their constructor).
Of course, a std::unique_ptr would also help here to conform to the rule of zero (cpp core guidelines C20), but that’s a different story.
So my suggestion would be to add the following exception to S3230:
In-class initialization should not be preferred when the type of the member is forward-declared (declared but not defined) in that header.