Given a base class for multiple derived class, the goal was to create a wrapper class that allowed an STL container to see objects with the base interface, event though different derived classes may actually be added to the container. (See Retrieve data from heterogeneous std::list).
After some tinkering, I came up with a new derived class that was a wrapper around a unique_ptr to the base class. However, the move constructor has me confused.
class Base {
friend class BaseWrapper;
virtual Base * clone () const = 0;
public:
virtual ~Base () {}
//... public interface
};
class Derived : public Base {
//... specific members for derived class
Base * clone () const { return new Derived(*this); }
public:
//... implement public interface
};
class BaseWrapper : public Base {
std::unique_ptr<Base> ptr_;
Base * clone () const { return ptr_->clone(); }
public:
BaseWrapper (const Base &b) : ptr_(b.clone()) {}
//... implement public interface by forwarding to ptr_
};
typedef std::list<BaseWrapper> BaseList;
int main () {
BaseList l;
l.push_back(Derived());
}
This does not compile with g++ 4.7.2.
Now, in order to use BaseWrapper, I can implement a public move constructor like this:
BaseWrapper (BaseWrapper &&bw) { ptr_.swap(bw.ptr_); }
And this works fine. But, if I make it private, it will not compile.
However, I found that instead of the above, I can instead define a private "copy" constructor (making it public also works, of course):
BaseWrapper (BaseWrapper &bw) { ptr_.swap(bw.ptr_); }
Could someone tell me if this was supposed to work, and why or why not? If it is supposed to work, why can I not make the move constructor private?
You can follow this link to the toy program illustrating the above in a more complete way.
[removed the erroneous diagnostic]
That actually compiles on gcc 4.8. It seems like gcc 4.7 takes BaseWrapper (const Base &) as a copy constructor(which is actually not), and implicitly deletes the move constructor(which would be expected behaviour if it were indeed a copy constructor).
Related
I am overloading operator= on a struct EqualTestBase, and operator= takes different parameters than are used to construct the struct.
struct EqualTestBase
{
EqualTestBase(int one) {}
EqualTestBase& operator=(std::string two)
{
//stuff
return *this;
}
};
It works fine on the base class. But a trival struct derived from it, EqualTestDerived, acts like it doesn't have the operator= member function.
struct EqualTestDerived : public EqualTestBase
{
EqualTestDerived(int one) : EqualTestBase(one) {}
};
void test()
{
EqualTestBase basetest(0);
basetest = "test"; //this is fine, compiles
EqualTestDerived derivedtest(0);
derivedtest = "test"; //this does not compile, says there is no constructor that takes type const char[5]
}
Do I have to redefine operator= on all derived structs, or is there a way to automatically pass down that functionality?
The derived class has an implicitly-declared copy-assignment operator, which hides the one declared in the base class. You can use using to bring it into scope:
struct EqualTestDerived : public EqualTestBase
{
EqualTestDerived(int one) : EqualTestBase(one) {}
using EqualTestBase::operator=;
};
operator= isn't inherited. If a class doesn't define operator= itself, the compiler will synthesize one for it (regardless of the fact that its base class does define an operator=).
If you want something that can be inherited (and can be virtual) you generally want to define it as a function with a different name. The generally accepted name for such a function is clone (though clone is normally more like a copy constructor, creating a new instance of an object, not just assigning to an existing one).
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.
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.
I have an abstract class and two concrete subclasses (Store), both with a pointer to another concrete subclass which is derived from an abstract class (Factory). Below is the code for the Store. I wanted to prevent memory leaks, so I started to write the copy control. I can't instantiate a new Factory however, because I don't know upfront what type it will be. What is a good practice to circumvent this? I could write the copy control in the concrete Stores, but then I have duplicate code.
I also tried to work with smart pointers instead, but there I find another difficulty. The snippet myFactory = std::make_shared<AbstractFactory>(ConcreteFactoryA()); apparently creates an AbstractFactory first, and then fills it with a ConcreteFactoryA. However, as the name suggests, AbstractFactory cannot be instantiated, as the compiler is telling me. Can you use shared_ptrs with abstract classes?
Code with plain pointers:
#pragma once
#include "AbstractFactory.h"
class AbstractStore
{
public:
// Copy control
AbstractStore(const AbstractStore& orig) : myFactory(new AbstractFactory(orig.myFactory)) {}
AbstractStore& operator=(const AbstractStore& orig) { return *this; } // TODO
~AbstractStore(void) {}
protected:
// Constructor
AbstractStore(void) {}
// Data members
AbstractFactory* myFactory;
};
class ConcreteStoreA : public AbstractStore
{
public:
ConcreteStoreA(void) { myFactory = new ConcreteFactoryA; }
~ConcreteStoreA(void) {}
};
class ConcreteStoreB : public AbstractStore
{
public:
ConcreteStoreB(void) { myFactory = new ConcreteFactoryB; }
~ConcreteStoreB(void) {}
};
Code with smart pointers:
#pragma once
#include "AbstractFactory.h"
#include <memory>
class AbstractStore
{
public:
// Copy control
AbstractStore(const AbstractStore& orig) : myFactory(orig.myFactory) {}
AbstractStore& operator=(const AbstractStore& orig) { myFactory = orig.myFactory; return *this; }
~AbstractStore(void) {}
protected:
// Constructor
AbstractStore(void) {}
// Data members
std::shared_ptr<AbstractFactory> myFactory;
};
class ConcreteStoreA : public AbstractStore
{
public:
ConcreteStoreA(void) { myFactory = std::make_shared<AbstractFactory>(ConcreteFactoryA()); }
~ConcreteStoreA(void) {}
};
class ConcreteStoreB : public AbstractStore
{
public:
ConcreteStoreB(void) { myFactory = std::make_shared<AbstractFactory>(ConcreteFactoryB()); }
~ConcreteStoreB(void) {}
};
You are not using make_shared correctly. Use:
std::make_shared<ConcreteFactory>();
You call it without any arguments here. make_shared is not accepting a constructed object but the arguments that are forwarded to it's constructor. In your case you would be forwarding to the copy constructor, which works poorly with abstract hierarchies. If you want copyable objects in hierarchies, use clone member functions with covariant return types.
This will return a shared_ptr<ConcreteFactory> which will be converted to shared_ptr<AbstractFactory> in the assignment (see (9) here. Also, use constructor initializer lists and virtual destructors.
You probably want one of these two things to make your smart pointer approach work:
Make ConcreteFactoryA and ConcreteFactoryB return a std::shared_ptr<AbstractFactory> or std::unique_ptr<AbstractFactory>. Simply assign, or better yet, initialize, in your "Store" classes
Initialize your shared_ptr<>s from raw pointers using std::shared_ptr<>::reset or the constructor
You would normally only use std::make_shared<> with smart pointers where you use new with raw pointers. In your case, you are simply assigning the pointer, so you shouldn't use it.
Recently one of my friend asked me how to prevent class inheritance in C++. He wanted the compilation to fail.
I was thinking about it and found 3 answers. Not sure which is the best one.
1) Private Constructor(s)
class CBase
{
public:
static CBase* CreateInstance()
{
CBase* b1 = new CBase();
return b1;
}
private:
CBase() { }
CBase(CBase3) { }
CBase& operator=(CBase&) { }
};
2) Using CSealed base class, private ctor & virtual inheritance
class CSealed
{
private:
CSealed() {
}
friend class CBase;
};
class CBase : virtual CSealed
{
public:
CBase() {
}
};
3) Using a CSealed base class, protected ctor & virtual inheritance
class CSealed
{
protected:
CSealed() {
}
};
class CBase : virtual CSealed
{
public:
CBase() {
}
};
All the above methods make sure that CBase class cannot be inherited further.
My Question is:
Which is the best method ? Any other methods available ?
Method 2 & 3 will not work unless the CSealed class is inherited virutally. Why is that ? Does it have anything to do with vdisp ptr ??
PS:
The above program was compiled in MS C++ compiler (Visual Studio).
reference : http://www.codeguru.com/forum/archive/index.php/t-321146.html
As of C++11, you can add the final keyword to your class, eg
class CBase final
{
...
The main reason I can see for wanting to do this (and the reason I came looking for this question) is to mark a class as non subclassable so you can safely use a non-virtual destructor and avoid a vtable altogether.
You can't prevent inheritance (before C++11's final keyword) - you can only prevent instantiation of inherited classes. In other words, there is no way of preventing:
class A { ... };
class B : public A { ... };
The best you can do is prevent objects of type B from being instantiated. That being the case, I suggest you take kts's advice and document the fact that A (or whatever) is not intended to be used for inheritance, give it a non-virtual destructor, and no other virtual functions, and leave it at that.
You are going through contortions to prevent further subclassing. Why? Document the fact that the class isn't extensible and make the dtor non-virtual. In the spirit of c, if someone really wants to ignore the way you intended this to be used why stop them? (I never saw the point of final classes/methods in java either).
//Note: this class is not designed to be extended. (Hence the non-virtual dtor)
struct DontExtened
{
DontExtened();
/*NOT VIRTUAL*/
~DontExtened();
...
};
1) is a matter of taste. If I see it correctly, your more fancy 2nd and 3rd solutions move the error in certain circumstances from link time to compile time, which in general should be better.
2) Virtual inheritance is needed to force the responsibility to initialize the (virtual) base class to the most derived class from where the base class ctor is no longer reachable.
To answer your question, you can't inherit from CBase because in virtual inheritance a derived class would need to have direct access to the class from which it was inherited virtually. In this case, a class that would derive from CBase would need to have direct access to CSealed which it can't since the constructor is private.
Though I don't see the usefulness of it all (ie: stopping inheritance) you can generalize using templates (I don't think it compiles on all compilers but it does with MSVC)
template<class T>
class CSealed
{
friend T; // Don't do friend class T because it won't compile
CSealed() {}
};
class CBase : private virtual CSealed<CBase>
{
};
If you can, I'd go for the first option (private constructor). The reason is that pretty much any experienced C++ programmer will see that at a glance and be able to recognize that you are trying to prevent subclassing.
There might be other more tricky methods to prevent subclassing, but in this case the simpler the better.
From C++11 onward, there is a clean solution that I am surprise not to see here. We can make the class final preventing any further inheritance.
class Foo final {};
class Bar: public Foo {}; // Fails to compile as Foo is marked as final
class myclass;
class my_lock {
friend class myclass;
private:
my_lock() {}
my_lock(const my_lock&) {}
};
class myclass : public virtual my_lock {
// ...
public:
myclass();
myclass(char*);
// ...
};
myclass m;
class Der : public myclass { };
Der dd; // error Der::dd() cannot access
// my_lock::my_lock(): private member
I found it here to give credit. I am posting here just other people can easily access
http://www.devx.com/tips/Tip/38482
To elaborate on Francis' answer: if class Bottom derives from class Middle, which virtually inherits from class Top, it is that most derived class (Bottom) that is responsible for constructing the virtually inherited base class (Top). Otherwise, in the multiple-inheritance/diamond-of-death scenario (where virtual inheritance is classically used), the compiler wouldn't know which of the two "middle" classes should construct the single base class. The Middle's constructor's call to the Top's constructor is therefore ignored when Middle is being constructed from Bottom:
class Top {
public:
Top() {}
}
class Middle: virtual public Top {
public:
Middle(): Top() {} // Top() is ignored if Middle constructed through Bottom()
}
class Bottom: public Middle {
public:
Bottom(): Middle(), Top() {}
}
So, in the the approach 2) or 3) in your question, Bottom() can't call Top() because it's inherited privately (by default, like in your code, but it's worth making it explicit) in Middle and thus is not visible in Bottom. (source)