子类化时覆盖静态变量

发布于 2024-07-14 03:07:39 字数 578 浏览 10 评论 0原文

我有一个类,我们称之为 A,在该类定义中我有以下内容:

static QPainterPath *path;

也就是说,我声明一个指向路径对象的静态(类范围)指针; 此类的所有实例现在都将具有相同的共享数据成员。 我希望能够在这个类的基础上进行构建,将其子类化为更专门的形式、分层行为,并且每个类都有自己独特的路径对象(但不必重复计算边界框或调用绘画例程等无聊的部分) )。

如果我将其子类化以创建类 F(例如),我希望 F 使用从 A 继承的绘图例程,但使用 F 中声明的静态(类范围)路径对象。我尝试将上面的声明放在私有部分(并在派生类 F 中重复它),并尝试将其放在受保护部分中,但没有任何乐趣。

我可以理解为什么会发生这种情况:

void A::paint() {
    this->path...

指的是 A::path 而不是 F::path,即使对象属于 F 类。

是否有一种优雅的方法来解决这个问题,并允许每个类维护一个静态路径对象,同时仍然使用基类中定义的绘图代码,并且所有类(可能基类除外)都是真实的且可实例化的?

I have a class, lets call it A, and within that class definition I have the following:

static QPainterPath *path;

Which is to say, I'm declaring a static (class-wide) pointer to a path object; all instances of this class will now have the same shared data member. I would like to be able to build upon this class, subclassing it into more specialised forms, layering behaviour, and with each class having its own unique path object (but not having to repeat the boring bits like calculating bounding boxes or calling the painting routines).

If I subclass it to create a class F (for example), I want F to use the inherited drawing routines from A, but to use the static (class-wide) path object declared in F. I have tried having the declaration above in the private section (and repeating it in the derived class F), and tried having it in the protected section, all with no joy.

I can sort of see why this is happening:

void A::paint() {
    this->path...

is referring to A::path instead of F::path, even when the object is of class F.

Is there an elegant way to get round this, and allow each class to maintain a static path object, while still using drawing code defined in the base class, and having all classes (except perhaps the base class) be real and instantiatable?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

一个人练习一个人 2024-07-21 03:07:39

使用虚方法来获取对静态变量的引用。

class Base {
private:
    static A *a;
public:
    A* GetA() {
        return a;
    }
};

class Derived: public Base {
private:
    static B *b;
public:
    A* GetA() {
        return b;
    }
};

请注意,这里 B 是从 A 派生的。 然后:

void Derived::paint() {
    this->GetA() ...
}

Use a virtual method to get a reference to the static variable.

class Base {
private:
    static A *a;
public:
    A* GetA() {
        return a;
    }
};

class Derived: public Base {
private:
    static B *b;
public:
    A* GetA() {
        return b;
    }
};

Notice that B derives from A here. Then:

void Derived::paint() {
    this->GetA() ...
}
画离情绘悲伤 2024-07-21 03:07:39

您也许可以对混合或

#include <stdio.h>

typedef const char QPainterPath;

class Base
{
public:
    virtual void paint() { printf( "test: %s\n", getPath() ); }
    virtual QPainterPath* getPath() = 0;
};

template <class TYPE>
class Holder : public Base
{
protected:
    static QPainterPath* path;
    virtual QPainterPath* getPath() { return path; }
};

class Data1 : public Holder<Data1>
{
};

class Data2 : public Holder<Data2>
{
};

template <> QPainterPath* Holder<Data1>::path = "Data1";
template <> QPainterPath* Holder<Data2>::path = "Data2";

int main( int argc, char* argv[] )
{
Base* data = new Data1;
data->paint();
delete data;

data = new Data2;
data->paint();
delete data;
}

我刚刚运行的 奇怪的重复模板模式进行变体这段代码在CodeBlocks中得到以下结果:

test: Data1
test: Data2

Process returned 0 (0x0)   execution time : 0.029 s
Press any key to continue.

You might be able to do a variant on a mix in or Curiously recurring template pattern

#include <stdio.h>

typedef const char QPainterPath;

class Base
{
public:
    virtual void paint() { printf( "test: %s\n", getPath() ); }
    virtual QPainterPath* getPath() = 0;
};

template <class TYPE>
class Holder : public Base
{
protected:
    static QPainterPath* path;
    virtual QPainterPath* getPath() { return path; }
};

class Data1 : public Holder<Data1>
{
};

class Data2 : public Holder<Data2>
{
};

template <> QPainterPath* Holder<Data1>::path = "Data1";
template <> QPainterPath* Holder<Data2>::path = "Data2";

int main( int argc, char* argv[] )
{
Base* data = new Data1;
data->paint();
delete data;

data = new Data2;
data->paint();
delete data;
}

I have just run this code in CodeBlocks and got the following:

test: Data1
test: Data2

Process returned 0 (0x0)   execution time : 0.029 s
Press any key to continue.
鹿童谣 2024-07-21 03:07:39

我还没有测试过这个,但是引入一个虚函数:

struct Base {

    void paint() {
         APath * p = getPath();
         // do something with p
    }

    virtual APath * getPath() {
         return myPath;
    }

    static APath * myPath;
};

struct Derived : public Base  {

    APath * getPath() {
         return myPath;
    }
    static APath * myPath;
};

可能是你想要的。 请注意,您仍然需要在某处定义两个静态变量:

APath * Base::myPath = 0;
APath * Derived::myPath = 0;

I haven't tested this, but introducing a virtual function:

struct Base {

    void paint() {
         APath * p = getPath();
         // do something with p
    }

    virtual APath * getPath() {
         return myPath;
    }

    static APath * myPath;
};

struct Derived : public Base  {

    APath * getPath() {
         return myPath;
    }
    static APath * myPath;
};

may be what you want. Note you still have to define the two statics somewhere:

APath * Base::myPath = 0;
APath * Derived::myPath = 0;
烟沫凡尘 2024-07-21 03:07:39

您可以使用虚函数来实现您的结果。 这可能是您最干净的解决方案。

class A
{
    protected:
        virtual QPainterPath *path() = 0;

    private:
        static QPainterPath *static_path;  /* Lazy initalization? */
};

QPainterPath *A::path()
{
    return A::static_path;
}

class F : public A
{
    protected:
        virtual QPainterPath *path() = 0;

    private:
        static QPainterPath *F_static_path;  /* Lazy initalization? */
};

QPainterPath *A::path()
{
    return F::F_static_path;
}

You can use virtual functions to achieve your result. This is probably your cleanest solution.

class A
{
    protected:
        virtual QPainterPath *path() = 0;

    private:
        static QPainterPath *static_path;  /* Lazy initalization? */
};

QPainterPath *A::path()
{
    return A::static_path;
}

class F : public A
{
    protected:
        virtual QPainterPath *path() = 0;

    private:
        static QPainterPath *F_static_path;  /* Lazy initalization? */
};

QPainterPath *A::path()
{
    return F::F_static_path;
}
○愚か者の日 2024-07-21 03:07:39

我知道这个问题已经得到解答,但是还有另一种方法可以通过辅助类和一些模板专门化来为多个类设置类似的静态变量的值。

它并没有完全回答这个问题,因为它与子类化没有任何关系,但我遇到了同样的问题,并且我找到了我想分享的不同解决方案。

示例:

template <typename T>
struct Helper {
  static QPainterPath* path;
  static void routine();
}

// Define default values
template <typename T> QPainterPath* Helper<T>::path = some_default_value;
template <typename T> void Helper<T>::routine { do_somehing(); }

class Derived {};

// Define specialized values for Derived
QPainterPath* Helper<Dervied>::path = some_other_value;
void Helper<Dervied>::routine { do_somehing_else(); }

int main(int argc, char** argv) {
  QPainterPath* path = Helper<Derived>::path;
  Helper<Derived>::routine();
  return 0;
}

优点:

  • 干净,编译时初始化
  • 静态访问(无实例化),
  • 您也可以声明专门的静态函数

缺点:

  • 无虚拟化,您需要确切的类型来检索信息

I know this question has been answered, but there is an other way to set the value of a similar static variable for multiple classes through a helper class and some template specialization.

It doesn't exactly answer the question since it is not connected with subclassing in any way, but I've encountered the same issue and I found a different solution I wanted to share.

Example :

template <typename T>
struct Helper {
  static QPainterPath* path;
  static void routine();
}

// Define default values
template <typename T> QPainterPath* Helper<T>::path = some_default_value;
template <typename T> void Helper<T>::routine { do_somehing(); }

class Derived {};

// Define specialized values for Derived
QPainterPath* Helper<Dervied>::path = some_other_value;
void Helper<Dervied>::routine { do_somehing_else(); }

int main(int argc, char** argv) {
  QPainterPath* path = Helper<Derived>::path;
  Helper<Derived>::routine();
  return 0;
}

Pros:

  • clean, compile time initialization
  • static access (no instantiation)
  • you can declare specialized static functions too

Cons:

  • no virtualization, you need the exact type to retrieve the information
薄荷→糖丶微凉 2024-07-21 03:07:39

您不能“覆盖”静态函数,更不用说静态成员变量了。

您需要的可能是一个虚函数。 这些只能是实例函数,因此如果没有类实例,将无法访问它们。

You can't "override" static functions, let alone static member variables.

What you need is probably a virtual function. These can only be instance functions, so they will not be accessible without class instance.

缱绻入梦 2024-07-21 03:07:39

您可能不希望覆盖静态变量。 也许你可以在你的类中存储一个指针?

class A
{
    public:
        A() :
            path(static_path)
        {
        }

    protected:
        A(QPainterPath *path)
            : path(path)
        {
        }

    private:
        QPainterPath *path;

        static QPainterPath *static_path;  /* Lazy initalization? */
};

class F : public A
{
    public:
        F() :
            A(F_static_path)
        {
        }

    private:
        static QPainterPath *F_static_path;  /* Lazy initalization? */
};

You probably don't want static variables to the overriden. Maybe you can store a pointer in your class instead?

class A
{
    public:
        A() :
            path(static_path)
        {
        }

    protected:
        A(QPainterPath *path)
            : path(path)
        {
        }

    private:
        QPainterPath *path;

        static QPainterPath *static_path;  /* Lazy initalization? */
};

class F : public A
{
    public:
        F() :
            A(F_static_path)
        {
        }

    private:
        static QPainterPath *F_static_path;  /* Lazy initalization? */
};
输什么也不输骨气 2024-07-21 03:07:39

如果您不关心外观,只需在使用路径之前使用 A:: 或 F:: 来选择正确的路径,或者如果您不喜欢 :: 则以不同的方式命名它们。

另一种选择是使用函数来解决这个问题,例如 virtual QPainterPath* GetPath() { return A::path; } 在 A 和 QPainterPath* GetPath() { return F::path; 实际上

,虽然这个问题只是关于代码的外观而不是它的作用,并且由于它并没有真正改变可读性,所以我不会为此担心......

If you don't care about the appearance just use A:: or F:: preceding the use of path to choose the correct one, or if you don't like :: name them differently.

Another option is to use a function to tidy this away, e.g. virtual QPainterPath* GetPath() { return A::path; } in A and QPainterPath* GetPath() { return F::path; } in F.

Really though this issue is just about how the code looks rather than what it does, and since it doesn't really alter readability I wouldn't fret about this...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文