5

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

#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* 的静态函数,唯一的问题是我希望为部分专业化进行初始化,而且似乎没有任何方法可以我知道在部分专业化中只重新定义一个函数,而不复制所有其他几乎保持不变的代码

4

6 回答 6

5

你也需要在你的子类中声明它。

struct derived : public base {
    static const char* componentName;
};
于 2010-11-22T03:13:26.690 回答
2

静态成员变量意味着有一个变量在该类的所有实例之间共享。尝试为基类设置一个值并为派生类设置一个不同的值是行不通的,因为它们都共享同一个变量,(显然)不能同时设置为两个不同的值。

于 2010-11-22T03:31:04.850 回答
2


我认为原因确实是因为以下是正确的:它们引用同一个对象,并且以 “谁笑到最后,笑得最好”的方式

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

两次初始化一个对象并不是一件好事。

干杯。

文茨

于 2012-10-02T20:27:51.597 回答
0

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

于 2010-11-22T03:27:17.043 回答
0

$9.4.2/2 - “在命名空间范围的定义中,静态数据成员的名称应使用 :: 运算符由其类名限定。”

和...

似乎无法在派生类上覆盖静态初始化?

请记住,覆盖仅适用于虚函数。

$10.3/2 - '如果虚成员函数 vf 在类 Base 和 Derived 类中声明,直接或间接从 Base 派生,则声明与 Base::vf 具有相同名称和相同参数列表的成员函数 vf,那么 Derived::vf 也是虚拟的(无论它是否如此声明)并且它会覆盖 97) Base::vf。

您可以尝试像这样重新运行组件名称,同时获得使用多态代码的优势。

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

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

int main(){}
于 2010-11-22T03:45:11.473 回答
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 为虚函数,以字符串形式返回类类型。此函数使用静态变量,也必须在派生类中重写。如果您忘记覆盖它,编译器将调用函数的基类版本,它将使用基类静态变量而不是派生类静态变量。因此,它将返回基类的对象类型。

于 2014-05-22T06:02:02.230 回答