QSharedData and inheritance - c++

I'm trying to make a type system while using QSharedData. The idea is simple, there will be a number of different data types, each of which is going to be derived from the base abstract class. I want to use QSharedData to store the actual data in each of them, but each of the derived classes is going to have different data stored inside. I'm trying to make the most basic example now, and having some troubles.
Let's say these are my base pure virtual classes:
class cAbstractData: public QSharedData
{
public:
cAbstractData(){ }
virtual int type() = 0;
};
class cAbstractValue
{
public:
cAbstractValue(){ }
virtual int type() = 0;
protected:
QSharedDataPointer<cAbstractData>data_;
};
Now let's say I want to make a class for representing a single value (as a minmalistic example that is). I'm deriving the cAtomicValue from the base value class, and I am also deriving a data class to hold the value:
class cAtomicData:public cAbstractData
{
public:
cAtomicData() { value_ = 0; }
int type(){ return 1; }
QVariant value_;//the actual value
};
class cAtomicValue:public cAbstractValue
{
public:
cAtomicValue() {
data_ = new cAtomicData;//creating the data object.
}
int type(){ return 1; }
};
Now at this stage it works just fine, and in the debugger I can see the right pointer type. But now I want to add a function for setting and getting the value, and I fail to understand how to do it. Let's take the setter as an example. To set the value, we must access the value_ member of cAtomicData class through the data_ member of the cAtomicValue class. However since the data_ holds a base-class pointer (cAbstractData), I'll have to cast it to the right type (cAtomicData) somehow. I tried doing this:
template<class T> void set( T value )
{
static_cast<cAtomicData*>(data_.data())->value_ = value;
}
it obviously doesn't work, because it called detach() and tries to make a copy of the base class which it can't since the base class is pure virtual. Then I tried to cast the pointer itself:
static_cast<cAtomicData*>(data_)->value_ = value;
but I'm getting an invalid static_cast ... error.
How do I do it, and am I even doing it the right way fundamentally?

You can switch to QExplicitlySharedDataPointer instead of QSharedDataPointer. In that way detach() won't be called whenever you're trying to obtain a non-const pointer to the cAbstractData object, which includes casting the QExplicitlySharedDataPointer<cAbstractData> object to a QExplicitlySharedDataPointer<cAtomicData> object. However, you will need to call detach() manually every time you want to make a modification to the cAbstractData if you are going to use copy-on-write. Maybe you can write a wrapper class to perform the detaching for you.
This method may be prefered over using QSharedPointer, since a QExplicitlySharedDataPointer is the same size as a normal pointer (and hence keeps binary compability) while a QSharedPointer is twice the size (see this blog entry).
Edit: Note that the cast from QExplicitlySharedDataPointer<cAbstractData> to QExplicitlySharedDataPointer<cAtomicData> is static, so you will have to guarantee that the object that is referenced actually is an object of the type cAtomicData (or of a subclass), or the behavior when using the pointer might be undefined.

I had a similar problem in my application and here is how I solved it. I have a BaseClass that is implemented using the Pimpl idiom and QExplicitlySharedDataPointer pointing to BaseClassPrivate. This class is inherited by DerivedClass whose private member is a DerivedClassPrivate inheriting BaseClassPrivate.
BaseClassPrivate has one float member named baseParam and DerivedClassPrivate has another float parameter named derivedParam.
I solved this problem doing the following :
Define a protected constructor BaseClass(BaseClassPrivate* p)
This is used to instantiate new derived classes with a pointer to DerivedClassPrivate
Define a virtual clone() method in both BaseClassPrivate and DerivedClassPrivate
This method is called to correctly copy the private class whenever a deep copy is needed. So, instead of calling 'QExplicitlySharedDataPointer::detach()', we check if the QSharedData reference counter is greater than 1, and then we call clone. Please note that QSharedData::ref is not in the documentation so this can change anytime (even though it seems unlikely to happen soon).
Static cast the d pointer in DerivedClass
I find it convenient to define a private dCasted() function.
To test this the virtual function foo() is introduced in BaseClassPrivate and DerivedClassPrivate, which returns either baseParam or derivedParam accordingly.
Here is the code :
BaseClass.h
class BaseClass
{
public:
BaseClass() : d(new BaseClassPrivate()) {}
BaseClass(const BaseClass& other) : d(other.d) {}
BaseClass& operator =(const BaseClass& other) {d = other.d; return *this;}
virtual ~BaseClass() {}
float baseParam() const {return d->baseParam;}
void setBaseParam(float value) {
detach(); // instead of calling d.detach()
d->baseParam = value;
}
float foo() const {return d->foo();}
protected:
BaseClass(BaseClassPrivate* p) : d(p) {}
void detach() {
// if there's only one reference to d, no need to clone.
if (!d || d->ref == 1) return; // WARNING : d->ref is not in the official Qt documentation !!!
d = d->clone();
}
QExplicitlySharedDataPointer<BaseClassPrivate> d;
};
DerivedClass.h
class DerivedClass : public BaseClass
{
public:
DerivedClass() : BaseClass(new DerivedClassPrivate()) {}
float derivedParam() const {return dCasted()->derivedParam;}
void setDerivedParam(float value) {
detach(); // instead of calling d.detach();
dCasted()->derivedParam = value;
}
private:
DerivedClassPrivate* dCasted() const {return static_cast<DerivedDataPrivate*>(d.data());}
};
BaseClassPrivate.h
class BaseClassPrivate : public QSharedData
{
public:
BaseClassPrivate() : QSharedData(), baseParam(0.0) {}
BaseClassPrivate(const BaseClassPrivate& other) :
QSharedData(other), baseParam(other.baseParam) {}
virtual ~BaseClassPrivate() {}
float baseParam;
virtual float foo() const {return baseParam;}
virtual BaseClassPrivate* clone() const {
return new BaseClassPrivate(*this);
}
};
DerivedClassPrivate.h
class DerivedClassPrivate : public BaseClassPrivate
{
public:
DerivedClassPrivate() : BaseClassPrivate(), derivedParam(0.0) {}
DerivedClassPrivate(const DerivedClassPrivate& other) :
BaseClassPrivate(other), derivedParam(other.derivedParam) {}
float derivedParam;
virtual float foo() const {return derivedParam;}
virtual BaseClassPrivate* clone() const {
return new DerivedClassPrivate(*this);
}
};
Now, we can do things such as :
Call virtual functions :
DerivedClass derived;
derived.setDerivedParam(1.0);
QCOMPARE(derived.foo(), 1.0); // proving that DerivedClassPrivate::foo() is called
Make copies from DerivedClass to BaseClass correctly :
BaseClass baseCopy = derived;
QCOMPARE(baseCopy.foo(), 1.0); // proving that DerivedClassPrivate::foo() is called
// even after copying to a BaseClass
Make copies from BaseClass to BaseClass respecting the original class and also make a copy-on-write correctly :
BaseClass bbCopy(baseCopy); // make a second copy to another BaseClass
QCOMPARE(bbCopy.foo(), 1.0); // still calling DerivedClassPrivate::foo()
// copy-on-write
baseCopy.setBaseParam(2.0); // this calls the virtual DerivedClassPrivate::clone()
// even when called from a BaseClass
QCOMPARE(baseCopy.baseParam(), 2.0); // verify the value is entered correctly
QCOMPARE(bbCopy.baseParam(), 1.0); // detach is performed correctly, bbCopy is
// unchanged
QCOMPARE(baseCopy.foo(), 1.0); // baseCopy is still a DerivedClass even after detaching
Hope this helps

I don't see any way to achieve what you're attempting here. As you've discovered, QSharedDataPointer needs to be templated on the actual type it contains.
You could make your base class a template, e.g.
template<class T>
class cAbstractValue
{
public:
cAbstractValue(){ }
virtual int type() = 0;
protected:
QSharedDataPointer<T> data_;
};
But I'm not sure I see what benefit you would get from that.

Since Qt 4.5 you can implement the ::clone() function for your type:
This function is provided so that you may support "virtual copy constructors" for your own types. In order to so, you should declare a template-specialization of this function for your own type, like the example below:
template<>
EmployeeData *QSharedDataPointer<EmployeeData>::clone()
{
return d->clone();
}
In the example above, the template specialization for the clone() function calls the EmployeeData::clone() virtual function. A class derived from EmployeeData could override that function and return the proper polymorphic type.
This function was introduced in Qt 4.5.
I've done so and it works.
Either your abstract base class and all derived classes need to implement a virtual BaseClass* clone() function you'd call from QSharedDataPointer::clone() or you need some other method (e.g. factory) to create a new instance with the same content as d.

Related

Accessing Private function using virtual function

How to avoid The private function calling indirectly using base class virtual function.
class baseclass{
public:
virtual void printmynumber() = 0;
};
class derivedclass : public baseclass
{
private:
int m_mynumber;
void printmynumber()
{
cout << m_mynumber << endl;
}
public:
derivedclass(int n)
{
m_mynumber = n;
}
};
void main()
{
baseclass *bObj = new derivedclass(10);
bObj->printmynumber();
delete bObj;
}
How to avoid the calling of private function?
You cannot.
void printmynumber() is part of the public API of baseclass, hence of derivedclass. If you wished derivedclass::printmynumber() not to be public, maybe derivedclass shouldn't inherit from baseclass.
As suggested in the comments, this is a violation of the Liskov substitution principle: the L in SOLID.
You can't do that with inheritance. Given a pointer to baseclass, the compiler only knows it has a public virtual function, so allows calling the function accordingly.
The derived class has elected to inherit from the base class, and has implemented a function with different access. But none of that is visible, given only a pointer to the base.
There is nothing preventing derivedclass::printmynumber() from being implemented to do nothing - which means if code calls it, there will be no observable effect (assuming absence of an expected effect is tolerable).
The real solution is to fix your design, not to try to work around deficiencies in it. Don't inherit derivedclass from baseclass. That way, no member function of derivedclass can be called at all, given only a pointer to baseclass, since the types are not related (passing a derivedclass * to a function expecting a baseclass * will normally be diagnosed as an error).
BTW: main() returns int, not void. Some compilers support void main() as a non-standard extension (and the documentation for some of those compilers falsely describes such a thing as standard) but it is better avoided.
The only way I can see to prevent it without modifying the base class, is to add another inheritance-layer between between the original base-class and the final derived class. In that middle class you make the function private or deleted. And then you use a pointer to that middle class as the base pointer.
Something like
class baseclass
{
public:
virtual void printmynumber() = 0;
};
struct middleclass : public baseclass
{
void printmynumber() = delete;
};
class derivedclass : public middleclass
{
private:
int m_mynumber;
void printmynumber()
{
cout << m_mynumber << endl;
}
public:
derivedclass(int n)
{
m_mynumber = n;
}
};
void main()
{
// Here use the middleclass instead of the baseclass
middleclass *bObj = new derivedclass(10);
// printmynumber is deleted in the middleclass and can't be called
// This will result in a build error
bObj->printmynumber();
delete bObj;
}
This of course requires modifications of all places where the original base class is used, but it won't need modifications to the base class itself. So it's a trade-off.

Dynamic binding of shared_ptr

I'm trying to implement something following the decorator pattern, but I cannot seem to obtain from a shared_ptr the same run-time behaviour I can get through normal pointers.
I have a basic class I (interface) with a virtual method, then I derive from it two classes:
class A (component) which will contain some data
class B (decorator) which derives from I and also contains a pointer to it and will implement some additional behaviour. I have a constructor that initialises the pointer to a certain I (or derived) object.
Then I want to be able to build a B object with its pointer pointing to an A, so that when I call the common methods I call the A ones not the I ones.
I can do this if I make the pointer in B in the usual way (in the code example, see the class B_basic and the object bb in the main).
But if I make this pointer like a shared_ptr to I it calls the method from I even if I build it pointing to an actual A (in code see the B_shared class and the object bs)
class I {
public:
virtual void method() {cout<<"I\n";}
virtual ~I() = default;
};
class A : public I {
public:
virtual void method() {cout<<"A\n";}
};
class B_shared : public I {
public:
shared_ptr<I> shared_pointer;
B_shared(const I& i) : shared_pointer(make_shared<I>(i)) {}
virtual void method() {
cout<<"B_shared > ";
shared_pointer->method();
}
};
class B_basic : public I {
public:
I* basic_pointer;
B_basic(I* i) : basic_pointer(i) {}
virtual void method() {
cout<<"B_basic > ";
basic_pointer->method();
}
};
int main() {
A a;
B_shared bs(a);
B_basic bb(&a);
bs.method(); // B_shared > I
bb.method(); // B_basic > A
}
What am I doing wrong?
This is object slicing.
In the following line you make a copy of the instance i of type A to type I. Thus the original type A is sliced to base type I.
shared_pointer(make_shared<I>(i))
In raw pointer version basic_pointer(i), you save the pointer itself, no slicing.

C++ Virtual Method return different derived types

Referencing this question: C++ virtual function return type
Let's consider the following set of objects.
class ReturnTypeBase
{
};
class ReturnTypeDerived1 : public ReturnTypeBase
{
public:
int x;
};
class ReturnTypeDerived2 : public ReturnTypeBase
{
public:
float y;
};
class Base
{
public:
virtual ReturnTypeBase* Get() = 0;
};
class Derived1: public Base
{
public:
virtual ReturnTypeDerived1* Get()
{
return new ReturnTypeDerived1();
}
};
class Derived2: public Base
{
public:
virtual ReturnTypeDerived2* Get()
{
return new ReturnTypeDerived2();
}
};
Can these objects be used in the following way?
Base* objects[2];
objects[0] = new Derived1();
objects[1] = new Derived2();
ReturnTypeDerived1* one = objects[0]->Get();
ReturnTypeDerived2* two = objects[1]->Get();
I'm assuming since the return types are covariant(?), that the set of objects above is legal C++. Will the appropriate Get() method be called? Can the pointers one/two be assigned the return value of the Get() method without casting?
The code will not compile as written. Because objects[0] has static type Base*, invoking the Get function results in a pointer with static type ReturnTypeBase* being returned. Since this is an overridden virtual function, the derived class's Get function will be called as you would expect, and the returned pointer would actually point to a ReturnTypeDerived1 object, but the compiler can't prove this. You would need a cast:
auto one = static_cast<ReturnTypeDerived1*>(objects[0]->Get());
auto two = static_cast<ReturnTypeDerived2*>(objects[1]->Get());
If you make ReturnTypeBase a polymorphic type, you can use dynamic_cast here instead to avoid undefined behaviour if you happen to be wrong about the dynamic type.
As written, you will get compiler errors on the .Get() call.
If you want to avoid that, make the assignment to base class..
ReturnTypeBase * one = objects[0].Get();
ReturnTypeBase * two = objects[1].Get();
As long as you access 'one' and 'two' through abstract methods defined in the base class, (eg. a 'toString()' method), you won't have problems with the internal data.
If you intend on treating the data the same across all instances of the base class, you might want to considering using a template class instead.

Virtual Function During Construction Workaround

I've got a base class that has a virtual function. I want to call that class during the construction because I want the function called for each of the derived classes. I know I can't call a virtual function during construction, but I can't think of an elegant (i.e., avoid repeating code) solution.
What are some work arounds to calling a virtual function during construction?
The reason I want to avoid this is because I don't want to have to create constructors that just call the base class.
class A {
public:
A() {
read();
}
// This never needs to be called
virtual void read() = 0;
}
class B:A {
public:
B():A() { };
read() { /*Do something special for B here.*/ }
}
class C:A {
public:
C():A() { };
read() { /*Do something special for C here.*/ }
}
PS: The Python way of doing this is simply to raise NotImplementedError in A::read(). I'm returning to C++ and I'm more rusty than I thought.
The FAQ perspective.
This is a Frequently Asked Question.
See the C++ FAQ item titled “Okay, but is there a way to simulate that behavior as if dynamic binding worked on the this object within my base class's constructor?”.
It’s very often a good idea to check the FAQ (and generally, googling or altavista’ing) before asking.
The question as “Derived class specific base initialization”.
To be clear, while the literal question above is
“What are some work arounds to calling a virtual function during construction?”
it is evident that what’s meant is
“How can a base class B be designed so that each derived class can specify part of what goes on during B construction?”
A major example is where C style GUI functionality is wrapped by C++ classes. Then a general Widget constructor might need to instantiate an API-level widget which, depending on the most derived class, should be a button widget or a listbox widget or whatever. So the most derived class must somehow influence what goes on up in Widget’s constructor.
In other words, we’re talking about derived class specific base construction.
Marshall Cline called that “Dynamic Binding During Construction”, and it’s problematic in C++ because in C++ the dynamic type of an object during class T construction and destruction, is T. This helps with type safety, in that a virtual member function is not called on a derived class sub-object before that sub-object has been initialized, or its initialization has started. But a major cost is that DBDI (apparently) can’t be done in a way that is both simple and safe.
Where the derived class specific init can be performed.
In the question the derived class specific action is called read. Here I call it derived_action. There are 3 main possibilities for where the derived_action is invoked:
Invoked by instantiation code, called two-phase construction.
This essentially implies the possibility of having a mostly unusuable not fully initialized object at hand, a zombie object. However, with C++11 move semantics that has become more common and accepted (and anyway it can be mitigated to some extent by using factories). A main problem is that during the second phase of construction the ordinary C++ protection against virtual calls on uninitialized sub-objects, due to dynamic type changes during construction, is not present.
Invoked by Derived constructor.
For example, derived_action can be invoked as an argument expression for the Base constructor. A not totally uncommon technique is to use a class template to generate most derived classes that e.g. supply calls of derived_action.
Invoked by Base constructor.
This implies that knowledge of derived_action must be passed up to the constructor, dynamically or statically. A nice way is to use a defaulted constructor argument. This leads to the notion of a parallel class hierarchy, a hierarchy of derived class actions.
This list is in order of increasing sophistication and type safety, and also, to the best of my knowledge, reflects the historical use of the various techniques.
E.g. in Microsoft’s MFC and Borland’s ObjectWindows GUI early 1990’ libraries two-phase construction was common, and that kind of design is now, as of 2014, regarded as very ungood.
This is the factory method approach, putting the factory into the base class:
class A {
public:
virtual void read() = 0;
template<class X> static X* create() {X* r = new X;X->read();return X;}
virtual A* clone() const = 0;
};
class B : public A {
B():A() { };
friend class A;
public:
void read() { /*Do something special for B here.*/ }
B* clone() const {return new B(*this);}
};
class C : public A {
C():A() { };
friend class A;
public:
void read() { /*Do something special for C here.*/ }
C* clone() const {return new C(*this);}
};
Added a clone-method with covariant return type as a bonus.
Using CRTP:
class A {
public:
// This never needs to be called
virtual void read() = 0;
virtual A* clone() const = 0;
};
template<class D, class B> struct CRTP : B {
D* clone() {return new D(*this);}
static D* create() {return new D();}
};
class B : public CRTP<B, A> {
B() { };
public:
void read() { /*Do something special for B here.*/ }
};
class C : public CRTP<C, A> {
C() { };
public:
void read() { /*Do something special for C here.*/ }
};
One way to achieve this, would be simply to delegate it to another class (that is perhaps a friend) and can be sure to be called when fully constructed.
class A
{
friend class C;
private:
C& _c; // this is the actual class!
public:
A(C& c) : _c(c) { };
virtual ~A() { };
virtual void read() = 0;
};
class B : public A
{
public:
B(C& c) : A(c) { };
virtual ~B() { };
virtual void read() {
// actual implementation
};
};
class C
{
private:
std::unique_ptr<A> _a;
public:
C() : _a(new B(*this)) { // looks dangerous? not at this point...
_a->read(); // safe now
};
};
In this example, I just create a B, but how you do that can depend on what you want to achieve and use templates on C if necessary, e.g:
template<typename VIRTUAL>
class C
{
private:
using Ptr = std::unique_ptr<VIRTUAL>;
Ptr _ptr;
public:
C() : _ptr(new VIRTUAL(*this)) {
_ptr->read();
};
}; // eo class C
The workaround is to call the virtual function after construction. You can then couple the two operations (construction + virtual call) in factory function. Here is the basic idea:
class FactoryA
{
public:
A *MakeA() const
{
A *ptr = CreateA();
ptr->read();
return ptr;
}
virtual ~FactoryA() {}
private:
virtual A *CreateA() const = 0;
};
class FactoryB : public FactoryA
{
private:
virtual A *CreateA() const { return new B; }
};
// client code:
void f(FactoryA &factory)
{
A *ptr = factory.MakeA();
}
As mentioned by Benjamin Bannier, you can use CRTP (a template which defines the actual read() function.) One problem with that method is that templates have to always be written inline. That can at times be problematic, especially if you are to write really large functions.
Another way is to pass a function pointer to the constructor. Although, in a way, it is similar to calling the function in your constructor, it forces you to pass a pointer (although in C++ you could always pass nullptr.)
class A
{
public:
A(func_t f)
{
// if(!f) throw ...;
(*f)();
}
};
class B : A
{
public:
B() : A(read) {}
void read() { ... }
};
Obviously, you have the "can't call other virtual functions" problem within the read() function and any function it calls. Plus, variable members of B are NOT yet initialized. That is probably a much worst problem in this case...
For that reason, writing it this way is safer:
B() : A()
{
read();
}
However, in cases like that, that may be the time when you an some for of init() function. That init() function can be implemented in A() (if you make it accessible: i.e. use public A when deriving) and that function can call all the virtual functions as expected:
class A
{
public:
void init()
{
read();
}
};
class B : public A
{
public:
...
};
I know a lot of people say that an init() function is evil because people who create a B object now need to know to call it... but there isn't much else you can do. That being said, you could have a form of factory, and that factory can do the init() call as required.
class B : public A
{
public:
static B *create() { B *b(new B); b->init(); return b; }
private:
B() { ... } // prevent creation without calling create()
};

Access inherited method during construction of base class?

I have a weird C++ problem where I'm not sure if it works correctly this way or If I missed something.
There is a class A which inherits from ABase. ABase and A both have a method Generate() while A::Generate() should overwrite ABase::Generate().
Generate() is called out of the constructor of ABase.
Now my problem:
I do a new A() which first jumps into constructor of A and from there into constructor of ABase. ABase::ABase() now calls Generate(). What I want to do: A::Generate() should be executed (since this overwrites ABase::Generate()).
Unfortunately it seems out of the constructor of ABase only ABase::Generate() is called and never A::Generate().
I gues that happens because A is not fully constructed at this stage? Or is there a way to let ABase::ABase() make use of A::Generate()?
You do not want A::Generate() to be executed, since this
would involve executing a function on a class which has not been
constructed. C++ has been designed intentionally so that during
construction, the dynamic type of the object is the type being
constructed, precisely to avoid this sort of problem.
It's not easy to work around, and definitely not pretty, but you may be able to do something like this:
class ABase
{
public:
ABase()
{
// Normal constructor, calls `Generate`
}
virtual void Generate() { ... }
// ...
protected:
struct do_not_call_generate_tag {};
const static do_not_call_generate_tag do_not_call_generate;
ABase(const do_not_call_generate_tag)
{
// Same as the normal `ABase` constructor, but does _not_ call `Generate`
}
};
class A : public ABase
{
public:
A()
: ABase(ABase::do_not_call_generate)
{
// Other initialization
PrivateGenerate();
}
void Generate()
{
PrivateGenerate();
}
private:
void PrivateGenerate()
{
// Do what your old `Generate` does
}
};
In order to have nicely constructed and initialized objects, I would separate these two tasks from each other:
class ABase
{
public:
virtual void Generate()
{
//...
}
};
class A: public ABase
{
public:
virtual void Generate()
{
//...
}
};
Now you have to perform both tasks explicitly
A *someA = new A();
someA->Generate();
...but you can group this inside e.g. a Create() method or redefine the new operator or the like.