наследование c ++ от базового класса virtal - PullRequest
0 голосов
/ 24 июня 2010

Я хочу сделать следующее:

class ErrorBase 
{
  public:
    void SetError(unsigned errorCode)
    {
      mErrorCode = errorCode;
    }

    char const* Explanation(unsigned errorCode) const
    {
      return errorExplanations[errorCode];
    }

  private:
    char const* errorExplanations[];
    unsigned mErrorCode;

};

class MyError : virtual public ErrorBase
{
  public:
    enum ErrorCodes {
      eNone,
      eGeneric,
      eMySpecificError
    };

    MyError() 
    { 

      // I want this to refer to the parent class's attribute, 
      // such that when Explanation() is executed, it uses this
      errorExplanations = {
        "no error",
        "error in MyClass",
        "specific error"
      }
    }
    ~MyError() { }
};

Но я получаю следующую ошибку в строке, объявившей errorExplanations в дочернем классе:

ошибка: ожидаемая первичная-выражение перед '{' токеном

Как мне объявить errorExplanations в дочернем классе, чтобы я мог создать экземпляр дочернего объекта, вызвать myChild.Explanation() и получить одну из строк ошибок, определенных вконструктор ребенка?

Любые предложения / исправления относительно моего использования const, virtual, public и т. д. приветствуются, спасибо!

Ответы [ 5 ]

2 голосов
/ 24 июня 2010

Вот еще один вариант.Пусть базовый класс получит массив данных через виртуальную функцию:

class ErrorBase 
{
  public:
    void SetError(unsigned errorCode)
    {
      mErrorCode = errorCode;
    }

    char const* Explanation(unsigned errorCode) const
    {
      return GetErrorTable()[errorCode];
    }

  private:
    virtual char const **GetErrorTable() const = 0;

  private:
    unsigned mErrorCode;

};

class MyError : virtual public ErrorBase
{
    virtual char const **GetErrorTable()
    {
      static char const *data[] = {
        "no error",
        "error in MyClass",
        "specific error"
      };
      return data;
    }
};
2 голосов
/ 24 июня 2010

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

Вам потребуется присвоить массиву одним из способов, которые вы обычно назначаете для массивов, например memcpy или цикл for.

Еще одна вещь, которая является неправильной, это то, что вы на самом деле не имеете доступа к массиву, который вы пытаетесь присвоить ему. Вам нужно будет предоставить его подклассам с защищенным или иметь функцию присваивания.

2 голосов
/ 24 июня 2010

Либо вы передаете массив сообщений об ошибках в базовый класс в его конструкторе (синтаксис может быть не идеальным, но, надеюсь, вы поняли):

class ErrorBase {
  public:
    ErrorBase(char const* errorExplanations[]) {
      this->errorExplanations = errorExplanations;
    }
    ...
  private:
    char const* errorExplanations[];
    ...
};

class MyError : virtual public ErrorBase {
  public:
    ...
    MyError() :
      ErrorBase( {
        "no error",
        "error in MyClass",
        "specific error"
      } )
    { }
    ...
};

Или вы делаете Explanation виртуальным и предоставляетеискомая реализация в производном классе:

class ErrorBase {
  public:
    ...
    virtual char const* Explanation(unsigned errorCode) const = 0;
  protected:
    unsigned mErrorCode;
};

class MyError : virtual public ErrorBase {
  public:
    ...
    MyError() :
      errorExplanations( {
        "no error",
        "error in MyClass",
        "specific error"
      } )
    { }

    virtual char const* Explanation(unsigned errorCode) const {
      return errorExplanations[errorCode];
    }
    ...
  private:
    char const* errorExplanations[];
};
0 голосов
/ 24 июня 2010

Другой вариант: сделать функцию Explanation(unsigned) const virtual, чтобы производные классы управляли своим собственным механизмом поиска сообщений об ошибках:

class ErrorBase 
{
public:
    virtual ~ErrorBase() { }

    void SetError(unsigned errorCode)
        : mErrorCode(errorCode)
    {
    }

    char const* Explanation() const { return this->Explanation(mErrorCode); }

    virtual char const* Explanation(unsigned errorCode) const
    {
        return errorExplanations[errorCode];
    }

private:
    unsigned mErrorCode;
};

class MyError : virtual public ErrorBase
{
public:
    enum ErrorCode {
        eNone = 0,
        eGeneric = 1,
        eMySpecificError = 2
    };

    MyError(ErrorCode c)
        : ErrorBase(static_cast<unsigned>(c))
    {
    }

    virtual ~MyError() { }

    virtual char const* Explanation(unsigned errorCode) const;
};

Затем скомпилированы строки ошибок для кодов ошибок MyError.в объектный файл:

// MyError.cpp
static const char* s_errorExplanations[] = {
        "no error",
        "error in MyClass",
        "specific error"
    };

char const* MyError::Explanation(unsigned errorCode) const
{
    return s_errorExplanations[errorCode];
}
0 голосов
/ 24 июня 2010

Попробуйте что-то вроде:

class ErrorBase 
{
  public:
    void SetError(unsigned errorCode)
    {
      mErrorCode = errorCode;
    }

    char const* Explanation(unsigned errorCode) const
    {
      return errorExplanations[errorCode];
    }

  private:
    char const** errorExplanations;
    unsigned mErrorCode;

};

class MyError : virtual public ErrorBase
{
  public:
    enum ErrorCodes {
      eNone,
      eGeneric,
      eMySpecificError
    };

    char const* child_strings[] = {"no error", "error in MyClass", "specific error"};

    MyError() 
    { 

      // I want this to refer to the parent class's attribute, 
      // such that when Explanation() is executed, it uses this
      errorExplanations = child_strings;
    }
    ~MyError() { }
};

Пусть ваш родительский класс содержит только указатель, ваш дочерний класс создаст и инициализирует массив, а затем установит указатель на массив в конструкторе вашего ребенка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...