【问题标题】:Trying to edit static variable of parent A class for all child class B试图为所有子类 B 编辑父类 A 类的静态变量
【发布时间】:2019-09-15 01:54:29
【问题描述】:

我对类中的静态变量有疑问。 我正在尝试编辑子类的静态变量而不编辑其他子类的静态变量。

头文件:

class A {
public:
    A() {}

    void printName() {qDebug() << _name; }    
    void changeName(QString name) {_name = name;}

private:
    static QString _name;
};
QString A::_name = QString("default");

class B : public A {
public:
    B() : A() {}
};

class C : public A {
public:
    C() : A() {}    
};

我正在尝试编辑 B 类的静态 _name 而不编辑 C 类的 _name。当我在 main.cpp 中尝试此代码时:

int main(int argc, char *argv[])
{
    A *a = new B{};
    A *b = new B{};
    A *c = new C{};

    a->printName();
    b->printName();
    c->printName();

    B *tmp = dynamic_cast<B*>(a);
    tmp->changeName("new");

    qDebug() << "Then";    

    a->printName();
    b->printName();
    c->printName();
}

这就是我所拥有的:

"default"
"default"
"default"
Then
"new"
"new"
"new"

有人知道我该如何解决这个问题吗?

这是我也尝试过的:

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

    void printName() {qDebug() << _name; }

    virtual void changeName(QString name) {_name = name;}
    private:
    static QString _name;
};

QString A::_name = QString("default");

class B : public A {
public:
    B() : A() {}

    void changeName(QString name) override {_name = name;}
private:
    static QString _name;
};

class C : public A {
public:
    C() : A() {}

    void changeName(QString name) override {_name = name;}
private:
    static QString _name;
};

【问题讨论】:

  • @FrançoisAndrieux 没有其他解决方案吗?因为我有很多子类......在每个子类中创建相同的静态成员会很遗憾
  • 为什么是static
  • 它是静态的,因为我希望这个变量在任何时候在我的子类 B 中都是相同的。
  • @starkmax 如果您希望每个子类具有不同的值,则需要不同的变量来保存这些值。目前只有一个变量。这就是 static 类变量的用途。

标签: c++ class inheritance casting static-variables


【解决方案1】:

A::_name 只有一个,在任何给定时间它只能有一个值。由于所有派生类型都使用相同的static 成员,因此它们必然都具有相同的_name 值。为了解决这个问题,每个派生类型都必须提供它自己的 static 成员。

为避免在每个派生类型中重复相同的成员,您可以在位于A 和派生类型BC 之间的模板化中间类中定义它们。每个模板特化都有它自己的static 成员。因此,只要每个派生类型都为中间类型的模板参数提供唯一值,它们就会有自己的名称。例如,将A 拆分为两个类:

#include <iostream>
#include <string>

class A {
public:
    virtual void printName() = 0;
    virtual void changeName(std::string name) = 0;
};

template<class T>
class A_impl : public A
{
public:
    void printName() override { 
        std::cout << _name << '\n';
    };
    void changeName(std::string name) override { 
        _name = std::move(name);
    };

private:
    static std::string _name;
};

template<class T>
std::string A_impl<T>::_name = "default";

那么每个派生类型都应该继承自A_impl,而不是A。通过向A_impl 提供它们自己的类型,您可以确保每个派生类型都提供一个唯一的模板参数:

class B : public A_impl<B> { };

class C : public A_impl<C> { };

现在你的测试应该打印出来了

default
default
default
Then
new
new
default

【讨论】:

  • 谢谢!这正是我正在搜索的内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-08-21
  • 1970-01-01
  • 2021-03-22
  • 2016-03-27
  • 1970-01-01
  • 2017-05-21
  • 1970-01-01
相关资源
最近更新 更多