Как инициализировать статическую переменную на унаследованном классе? - PullRequest
3 голосов
/ 25 января 2012

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

Каков наилучший подход для достижения этой цели? Это моя текущая попытка:

class Ball {
  public:
    virtual ~Ball();
    Ball ();

  protected:
    static string file;
    static int size;
    node shape;
};

class TenisBall: public Ball {};
class OtherBall: public Ball {};

Ball::Ball () {
  shape = // do something with file and size
};

Ball::~Ball () {
  delete shape;
};

string TenisBall::file = "SomeFile";
int TenisBall::size = 20;

string OtherBall::file = "OtherFile";
int OtherBall::size = 16;

Моя проблема в том, что я не могу установить статические значения для классов TenisBall и OtherBall, компилятор принимает их, только если я изменяю TenisBall и OtherBall на Ball в последних двух строках кода. Как я могу сделать это? Это лучший подход?

EDIT:

Следуя предоставленным ответам, я решил попытаться реализовать его с помощью виртуальных функций. Вот мой код:

class Ball {
  public:
    Ball () {
      shape = // do something with getSize and getFile
    };

    ~Ball () {
      delete shape;
    };

  protected:
    virtual string getFile(){ return "Fake"; };
    virtual int getSize(){ return 10; };

    node shape;
};

class TenisBall: public Ball {
  int getSize() { return 16; };
  string getFile() { return "TennisBall.jpg"; };
};

int main() {
  TenisBall ball;
  return 1;
};

Но, хотя мой редактор (xCode) не выдает никакой ошибки, при попытке компиляции llvm выдает следующую ошибку:

недопустимый символ '_' в идентификаторе пакета в столбце 22. Эта строка должна быть идентификатором универсального типа (UTI), который содержит только буквенно-цифровые (AZ, az, 0-9), дефис (-) и точку (.) символы.

Ответы [ 3 ]

4 голосов
/ 25 января 2012

То, что вы пытаетесь, невозможно. Как только статическая переменная объявлена ​​в классе, для этого класса появляется только одна переменная, и даже производные классы не могут это изменить (поэтому вы не можете изменить Ball::file, чтобы сделать что-то другое для TennisBall, что бы это ни значило).

Самый простой обходной путь, вероятно, заключается в замене Ball::file на виртуальную функцию (возвращающую string или string& на что-то, что может быть даже классом или статической функцией), которую вы можете переопределить в производном классе.

1 голос
/ 25 января 2012

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

template<typename T>
class Ball {
    static int size;
};

template<typename T> int Ball<T>::size = 0;

class TennisBall : public Ball<TennisBall> {

};

template<> int Ball<TennisBall>::size = 42;
0 голосов
/ 25 января 2012

Очевидно, что статики здесь нет-нет, если вы их используете, у вас есть одна копия данных в памяти независимо от того, сколько экземпляров производных классов у вас есть, так что вы в конечном итоге перезаписываете данные каждый раз.

Как насчет чего-то подобного ниже, одного общего конструктора в Ball, который обрабатывает размер и имя файла?

class Ball {
  public:
    virtual ~Ball();
    Ball ();
    Ball (int curr_size, string curr_filename);

  protected:
    string file;
    int size;
    node shape;
};

class TenisBall: public Ball {
   TennisBall(int size, string filename)
     :this(curr_size, curr_filename)
   {
   }


};
class OtherBall: public Ball {
   OtherBall(int size, string filename)
     : this(curr_size, curr_filename)
   {
   }

};

Ball::Ball () {
  shape = // do something with file and size
};

Ball::Ball(int curr_size, string curr_filename) {
    shape = // whatever
    curr_size = size;
    curr_filename = filename;
}

Ball::~Ball () {
  delete shape;
};

// ....
Ball *b = new TennisBall(16, "c:/tennisball_photo.jpg");

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