Как создать производные классы из базового класса с помощью шаблонного программирования на C ++? - PullRequest
2 голосов
/ 13 декабря 2010

Мне нужно создать ряд классов (более 50) из базового класса, где единственное отличие заключается в именах производных классов.

Например, мой базовый класс определяется как:

class BaseError : public std::exception
{
private:
    int osErrorCode;
    const std::string errorMsg;

public:
    int ec;
    BaseError () : std::exception(), errorMsg() {}

    BaseError (int errorCode, int osErrCode, const std::string& msg)
         : std::exception(), errorMsg(msg)
    {
       ec = errorCode;
       osErrorCode = osErrCode;
    }

    BaseError (const BaseError& other)
        : std::exception(other), errorMsg(other.errorMsg)
    {
        ec  = other.errorCode;
        osErrorCode = other.osErrorCode;
    }

    const std::string& errorMessage() const { return errorMsg; }

    virtual ~BaseError() throw(){}

}

Мне нужно создать множество производных классов из этого базового класса, каждый из которых имеет свои собственные конструкторы, конструктор копирования и функцию виртуального деструктора, в настоящее время я копирую / вставляю код, меняя имена, где это необходимо:

class FileError : public BaseError{
private:
    const std::string error_msg;

public:
    FileError () :BaseError(), error_msg() {}

    FileError (int errorCode, int osErrorCode, const std::string& errorMessage)
        :BaseError(errorCode, osErrorCode, errorMessage){}

    virtual ~FileError() throw(){}
};

Вопрос : Есть ли способ создать эти классы с использованием шаблонов, чтобы реализация не повторялась?

Ответы [ 3 ]

7 голосов
/ 13 декабря 2010

Полагаю, вы хотите создать иерархию классов, чтобы вы могли использовать динамическую диспетчеризацию в своих предложениях catch (полагаясь на компилятор для определения правильного типа) для реализации пользовательской обработки ошибок. Вы можете сделать это, сохранив класс BaseError как есть, а затем добавив класс шаблона, для которого вы затем предоставите несколько экземпляров. Учтите это:

class BaseError : public std::exception
{
private:
    int osErrorCode;
    const std::string errorMsg;

public:
    int ec;
    BaseError () : std::exception(), errorMsg() {}

    BaseError (int errorCode, int osErrCode, const std::string& msg)
         : std::exception(), errorMsg(msg)
    {
       ec = errorCode;
       osErrorCode = osErrCode;
    }

    // ...
};

template <int T>
class ConcreteError : public BaseError {
public:
    ConcreteError () :BaseError(), error_msg() {}

    ConcreteError (int errorCode, int osErrorCode, const std::string& errorMessage)
        :BaseError(errorCode, osErrorCode, errorMessage){}
};

Теперь вы можете настроить несколько определений типов:

typedef ConcreteError<0> FileError;
typedef ConcreteError<1> NetworkError;
typedef ConcreteError<2> DatabaseError;
// ...

Теперь у вас есть иерархия с тремя различными классами ошибок.

4 голосов
/ 13 декабря 2010

Если реализации идентичны, создайте перечисление и шаблон для него.

enum error {
    file_error,
};
template<error e> class my_exception : public BaseError {
    ....
};
typedef my_exception<file_error> file_exception;
0 голосов
/ 13 декабря 2010

Если реализация точно такая же, и вы просто хотите различное имя для каждого класса, тогда простой typedef сделает вашу работу.

И если есть небольшая разница в реализации, но не в интерфейсе, то вы можетенаверное нужны шаблоны.Затем рассмотрим также основанный на политике дизайн .

...