Reputation:
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?
Upvotes: 20
Views: 31933
Reputation: 492
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;
}
Upvotes: 2
Reputation: 1424
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.
Upvotes: 12
Reputation:
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;
Upvotes: 8
Reputation: 3113
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...
Upvotes: 0
Reputation: 90012
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;
}
Upvotes: 3
Reputation: 7639
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() ...
}
Upvotes: 23
Reputation: 90012
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? */
};
Upvotes: 0
Reputation: 115721
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.
Upvotes: 1