PDA

View Full Version : Can I throw exceptions from the constructor?



8Observer8
23rd August 2014, 08:19
Hello

Sorry for my English in advance!

Can I throw exceptions from the constructor?

I want to send data to the Serial Port. And I want to control errors via exceptions. I've written my own exception for it:

PortError.h


#ifndef PORTERROR_H
#define PORTERROR_H

#include <stdexcept>
#include <string>

class PortError : public std::runtime_error
{
public:
PortError( const std::string &errorText ) : std::runtime_error( "" )
{
m_message = "Error: " + errorText;
}

virtual ~PortError() throw()
{

}

virtual const char *what() const throw()
{
return m_message.c_str();
}

std::string getMessage()
{
return m_message;
}

private:
std::string m_message;
};

#endif // PORTERROR_H


I will use it like this:


void MainWindow::on_startTransmissionButton_clicked()
{
QString text = ui->valueForSendingLineEdit->text();
QByteArray data;
data.append( text );
try {
m_sender->send( data );
} catch ( const PortError &e ) {
QMessageBox::information( this, "Error", QString( e.what() ) );
return;
} catch ( ... ) {
QMessageBox::information( this, "Error", "Error: unknown exception" );
return;
}
}


Sender.h


#ifndef SENDER_H
#define SENDER_H

#include <QSerialPort>
#include <QString>
#include "PortError.h"

class Sender
{
public:
Sender( const QString &portName,
QSerialPort::BaudRate baudRate = QSerialPort::Baud9600,
QSerialPort::DataBits dataBits = QSerialPort::Data8,
QSerialPort::Parity parity = QSerialPort::NoParity,
QSerialPort::StopBits stopBits = QSerialPort::OneStop,
QSerialPort::FlowControl flowControl = QSerialPort::NoFlowControl );

~Sender();

void send( const QByteArray &data ) throw( PortError );

private:
QSerialPort m_port;
QString m_portName;
QSerialPort::BaudRate m_baudRate;
QSerialPort::DataBits m_dataBits;
QSerialPort::Parity m_parity;
QSerialPort::StopBits m_stopBits;
QSerialPort::FlowControl m_flowControl;
};

#endif // SENDER_H


Sender.cpp


#include "Sender.h"

Sender::Sender(const QString &portName,
QSerialPort::BaudRate baudRate,
QSerialPort::DataBits dataBits,
QSerialPort::Parity parity,
QSerialPort::StopBits stopBits,
QSerialPort::FlowControl flowControl ) :
m_port( portName ),
m_baudRate( baudRate ),
m_dataBits( dataBits ),
m_parity( parity ),
m_stopBits( stopBits ),
m_flowControl( flowControl )
{
// Set the port name
m_port.setPortName( m_portName );

// Open the port
if ( !m_port.open( QIODevice::WriteOnly ) ) {
throw PortError( m_port.errorString().toStdString() );
}

m_port.setBaudRate( m_baudRate );
m_port.setDataBits( m_dataBits );
m_port.setParity( m_parity );
m_port.setStopBits( m_stopBits );
m_port.setFlowControl( m_flowControl );
}

Sender::~Sender()
{
m_port.close();
}

void Sender::send( const QByteArray &data ) throw( PortError )
{
// Write data to the port
if ( m_port.write( data ) == -1 ) {
throw PortError( m_port.errorString().toStdString() );
}
}


Added after 14 minutes:

Can I use it? Is it right?



MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);

try {
m_sender = new Sender( "COM1" );
} catch ( const PortError &e ) {
QMessageBox::information( this, "Error", QString( e.what() ) );
} catch ( ... ) {
QMessageBox::information( this, "Error", "Error: unknown exception" );
}
}

ChrisW67
23rd August 2014, 10:14
Yes, if you wish. Exceptions are a standard part of C++ and often the best way to handle unrecoverable problems in a constructor (you cannot use a return value). The destructor will not be called if the constructor throws, so you need to be careful to ensure anything the constructor has allocated before the exception is wrapped in a smart pointer or similar. (Does not seem to affect your example)

8Observer8
23rd August 2014, 14:19
Thank you!

My application crash when I call .isOpen() Method. Why?



void Sender::send( const QByteArray &data ) throw( PortError )
{
if ( !m_port.isOpen() ) {
throw PortError( m_port.errorString().toStdString() );
}

// Write data to the port
if ( m_port.write( data ) == -1 ) {
throw PortError( m_port.errorString().toStdString() );
}
}

ChrisW67
23rd August 2014, 22:07
We can only guess. The actual error message/crash dump and your debugger will help you work it out. Post the stack backtrace and other details if you cannot work it out.

8Observer8
27th August 2014, 09:39
I was helped here: http://www.prog.org.ru/index.php?topic=27520

The error on this line "m_port( portName ),"


Sender::Sender( const QString &portName,
QSerialPort::BaudRate baudRate,
QSerialPort::DataBits dataBits,
QSerialPort::Parity parity,
QSerialPort::StopBits stopBits,
QSerialPort::FlowControl flowControl ) :
m_port( portName ),
m_baudRate( baudRate ),
m_dataBits( dataBits ),
m_parity( parity ),
m_stopBits( stopBits ),
m_flowControl( flowControl )
{
// Set the port name
m_port.setPortName( m_portName );

I should have written m_portName instead m_port.

I replaced "QSerialPort m_port;" on "QSerialPort m_serialPort;" And I delete the m_portName because I can to write m_serialPort( portName ) in the "Sender" constructor.

It is my project: https://github.com/8Observer8/ComPort