не может переопределить статическую инициализацию в производном классе - PullRequest
5 голосов
/ 22 ноября 2010

Я пытаюсь обеспечить различные статические инициализации для классов в иерархии, но когда я попытался с этим кодом:

#include <iostream>

using namespace std;

struct base {
static const char* componentName;
};
const char* base::componentName = "base";

struct derived : public base {};

const char* derived::componentName = "derived";

int main() {

cout << base::componentName << endl;
cout << derived::componentName << endl;
}

Я закончил с этой ошибкой сборки:

test.cpp:15: error: ISO C++ does not permit ‘base::componentName’ to be defined as ‘derived::componentName’
test.cpp:15: error: redefinition of ‘const char* base::componentName’
test.cpp:11: error: ‘const char* base::componentName’ previously defined here

Кажется, что статические инициализации не могут быть переопределены в производных классах? Если это не работает, я всегда мог бы определить componentName как статическую функцию, которая возвращает const char *, единственная проблема с этим, я как бы надеялся выполнить инициализацию для частичных специализаций, и, похоже, нет никакого способа, которым я знаю о том, чтобы переопределить только одну функцию в частичной специализации, не копируя весь другой код, который останется в основном таким же

Ответы [ 6 ]

6 голосов
/ 22 ноября 2010

Вы должны объявить это и в своем подклассе.

struct derived : public base {
    static const char* componentName;
};
2 голосов
/ 03 октября 2012

Я думаю, что причина действительно в том, что верно следующее:&base::componentName == &derived::componentNameони ссылаются на один и тот же объект и дважды инициализируют объект в«кто смеется последним, тот смеется лучше» не может быть хорошей вещью.

Приветствия.

Vintz

2 голосов
/ 22 ноября 2010

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

0 голосов
/ 22 мая 2014

если вы попытаетесь инициализировать статическую переменную в производном классе перед объявлением в производном классе, вы получите ошибку переопределения, потому что производный класс подобен базовому классу, а статические переменные определены только один раз для класса, поэтому вторая инициализация вызывает ошибку переопределения.

Один из правильных способов сделать то, что вы намереваетесь, приведен ниже:

struct a {
    virtual const string& getClassType() const {
        return ClassName;
    }
    static string ClassName;
};
string a::ClassName = "StructA";

struct c : public a {
    const string& getClassType() const {
        return ClassName;
    }
    static string ClassName;
};
string c::ClassName = "StructC";

a* a1 = new c();
cout << a1->getClassType() << endl;

ПРИМЕЧАНИЕ В приведенном выше коде getClassType является виртуальной функцией и возвращает тип класса вформат строкиЭта функция использует статическую переменную и должна быть переопределена и в производном классе.Если вы забудете переопределить его, компилятор вызовет версию функции базового класса и будет использовать статическую переменную базового класса вместо статической переменной производного класса.Таким образом, он возвращает тип объекта базового класса.

0 голосов
/ 22 ноября 2010

$ 9.4.2 / 2 - "В определении на область имен, имя член статических данных должен быть квалифицирован его имя класса, используя :: оператор ".

И ...

Кажется, что статические инициализации не может быть переопределено на производном классы?

Пожалуйста, помните, что переопределение только для виртуальных функций.

$ 10,3 / 2 - «Если виртуальный член функция vf объявлена ​​в классе База и в классе Производные, производные прямо или косвенно с базы, а функция-член VF с тем же именем и тот же список параметров, что и Base :: vf объявлено, тогда Derived :: vf также виртуальный (так ли это объявил) и переопределяет97) Основание :: ФВ.

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

struct base{
   virtual char const* myname(){
      return "base";
   }
   virtual ~base(){}
};

struct derived : base{
   virtual char const* myname(){
      return "derived";
   }
};

int main(){}
0 голосов
/ 22 ноября 2010

«переопределение» и «наследование» - это термины, которые имеют смысл только для объектов. Переменные класса не участвуют в наследовании объекта.

...