无法覆盖派生类中的静态初始化

时间:2010-11-22 03:09:56

标签: c++ inheritance static-initialization

我正在尝试为层次结构中的类提供不同的静态初始化,但是当我尝试使用此代码时:

#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 个答案:

答案 0 :(得分:6)

您也需要在子类中声明它。

struct derived : public base {
    static const char* componentName;
};

答案 1 :(得分:2)

静态成员变量意味着在该类的所有实例之间共享一个变量。尝试为基类创建一个值并为派生类设置不同的值不起作用,因为它们共享同一个变量,这显然不能同时设置为两个不同的值。

答案 2 :(得分:2)


我认为原因是因为以下情况属实:

&base::componentName == &derived::componentName

它们引用相同的对象,并在一个初始化对象两次 “谁笑到最后,笑得最好”的方式不可能是一件好事。

干杯。

Vintz

答案 3 :(得分:0)

'覆盖'和'继承'是仅对对象有意义的术语。类变量不参与对象继承。

答案 4 :(得分:0)

  

$ 9.4.2 / 2 - “在定义中   命名空间范围,名称   静态数据成员应具备资格   通过类名使用::   运算符“。

和...

  

似乎静态初始化   不能在派生上重写   类?

请记住,覆盖仅适用于虚拟功能。

  

$ 10.3 / 2 - '如果是虚拟会员   函数vf在类中声明   基础和类Derived,派生   直接或间接来自Base,a   成员函数vf具有相同的名称   与Base :: vf相同的参数列表是   声明,然后Derived :: vf也是   虚拟的(无论是否如此   宣布)并覆盖97)   基:: VF。

您可以尝试重新启动组件名称,同时获得使用多态代码的优势。

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

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

int main(){}

答案 5 :(得分:0)

如果在派生类中声明之前尝试初始化派生类中的静态变量,则会得到重定义错误,因为派生类类似于基类,静态变量仅为类定义一次,因此第二次初始化会导致重定义错误。

执行您的意图的正确方法之一是:

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是虚函数,并以字符串格式返回类类型。 此函数使用静态变量,也必须在派生类中重写。如果您忘记覆盖它,编译器将调用该函数的基类版本,它将使用基类静态变量而不是派生类静态变量。所以,它会回来 基类的对象类型。