I need a static method of my Base class to have a default parameter value of type Derived.
Is there a way to implement this without use of overloading? (see here).
class Base;
class Derived;
Derived make_derived(void);
class Base
{
public:
static void problem_here(Base && = make_derived());
};
class Derived : public Base
{
};
Derived make_derived()
{
return Derived();
}
... gives me an error about the usage of the incomplete type Derived. How ever, I cannot place the definition of Derived in front of problem_here because it must be defined after the definition of its base class Base.
Unfortunately, returning a pointer from make_derived is not an option.
Overloading problem_here is the only thing I came up with until now, but as the "real" problem_here method takes 2 (and another one 3) parameters, and it's part of a library, this gives me ...
static void problem_here(Thing const &, Base const &);
static void problem_here(Thing const &, Base &&);
static void problem_here(Thing const &); // Default param "hack"
static void problem_here(Thing &&, Base const &);
static void problem_here(Thing &&, Base &&);
static void problem_here(Thing &&); // Default param "hack"
.. for only the two parameter case.
Is there a way to avoid writing all those function signatures, while still maintaining the same performance (no unneccessary copy/move construction for any parameter constellation) and same behaviour on the caller site?
I should add that there are multiple functions like problem_here and all need access to the protected constructor of Derived (and to those of its many siblings). So the main reason to make these methods static members of Base is to be able to friend class Base; in each of the derived classes instead of friending every function.
Refactoring showed me, that I could move the code accessing the protected constructors of the derived classes into a single factory function. That way, I'm able to move the functions with the default parameters outside Base and let the call the factory. Now I still have to friend every one of those functions, but only a single time (in Base to give them access to the factory). I could circumvent this by placing all functions into a helper class and friending it instead, but that looks like a hack to me.
class Base
{
friend class Helper; // The Hack
friend void no_problem_here(Base &&); // No hack, more writting
protected:
static void factory(Thing && from_which_I_can_construct_the_correct_derived_class);
// return type void to keep it simple, move parameter type because special cases
// handled in "trampoline" functions and a copy of the Thing must be stored either
// way.
};
class Derived : public Base
{
friend class Base;
// protected constructor omited for simplicity.
}
void no_problem_here(Base && = make_derived());
// ...
void no_problem_here(Base && b)
{
// work, and then call Base::factory
}
// or
class Helper
{
protected:
// Constructors ...
public:
static void no_problem_either(Base && = make_derived());
};
You can make declarations multiple times, so the following workaround might help:
class Base;
class Derived;
Derived make_derived(void);
class Base
{
public:
static void problem_here(Base &&);
};
class Derived : public Base {};
void Base::problem_here(Base && = make_derived()) { /* ... */ }
If there's a problem factoring the code like that, you can always insert a little trampoline function:
class Base
{
public:
static void problem_here(Base &&);
private:
static void problem_here_impl(Base &&);
};
inline void Base::problem_here(Base && x = make_derived())
{ problem_here_impl(std::move(x)); }
Related
I would like to combine the concepts of polymorphism and friendship. I am making a pure virtual member function of a base class a friend of another class. I would then like to override this pure virtual member function in the classes derived from that base class, and access private member data of the class who has such function as friend. See the code snippet below. The compiler complains when I refer to my_int in the derived classes member function add(). I understand friendship is a 1-to-1 relationship, but I wonder if there is any way around it so as to implement polymorphism. Do I just have to make the member functions of the different derived classes friends of the foo() class?
class foo {
private:
int my_int{};
public:
friend virtual int base::add();
};
class base {
public:
virtual int add() = 0;
};
class derived_1 : public base {
public:
int add() {
return my_int + 1;
}
};
class derived_2 : public base {
public:
int add() {
return my_int + 2;
}
}
First, with what you've displayed it's not going to work because my_int is a member of foo but in the base class tree there is no 'foo' to get the member from.
The easy answer would be to make the function take an int argument and do away with the use of friend entirely.
struct derived2 : base
{
int add(int arg) { return arg + 2; }
};
The use of 'friend' should make you seriously question whether what you are doing is a good answer, sometimes the answer to that question is 'yes' but not often. And the more friends you need the less often the answer remains 'yes'.
Another way would be to add a function to base:
int get_arg(foo & f) { return f.my_int; }
and make that function the friend rather than add, get_arg() would be called from each derived's add() in order to get the value to work with but get_arg is not itself virtual.
You might want to look here:
https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Virtual_Friend_Function
Intent
Simulate a virtual friend function.
Solution and Sample Code
Virtual friend function idiom makes use of an extra indirection to
achieve the desired effect of dynamic binding for friend functions. In
this idiom, usually there is only one function that is a friend of the
base class of the hierarchy and the friend function simply delegates
the work to a helper member function that is virtual. The helper
function is overridden in every derived class, which does the real job
and the friend function just serves as a facade.
class Base {
public:
friend ostream& operator << (ostream& o, const Base& b);
// ...
protected:
virtual void print(ostream& o) const
{ ... }
};
/* make sure to put this function into the header file */
inline std::ostream& operator<< (std::ostream& o, const Base& b)
{
b.print(o); // delegate the work to a polymorphic member function.
return o;
}
class Derived : public Base {
protected:
virtual void print(ostream& o) const
{ ... }
};
It is very easy that we can make sure derived class must implement interface defined in base class.
That is pure virtual function.
For example:
class BaseClass
{
...
virtual void print()=0;
...
}
class DerivedClass :public BaseClass
{
// function must be implement, otherwise compiler will complain ...
void print()
{
}
};
Can we defined a static interface in base class and make sure the interface must be implement in derivate class?
I want something like this
class BaseClass
{
...
static void print(); // base class only define static interface
...
}
class DerivedClass :public BaseClass
{
// derived class must implement interface, otherwise compiler will complain ...
static void print()
{
}
};
I have no idea about this.
Thanks for your time.
It is not possible to make a virtual static function. For the simple reason that when calling a static function, you always know the class that defines that function in compile time. Unlike virtual functions, where you don't know the type of the object whose method you're calling.
For example:
class A
{
public:
virtual void f() {printf("A");}
};
class B : public A
{
virtual void f() override {printf("B");}
};
void g(A& a)
{
a.f();
}
int main()
{
B b;
g(b);
return 0;
}
In the above example, inside the function g, the correct function is invoked (B::f). Even though while compiling the function it is not known what the type of its argument is (it could be A or any class derived from A).
Without making f() virtual, you would have overloaded the method f, rather than overridden it. Which means that in the following example, the output would be "A", even though you might expect it to be "B":
class A
{
public:
void f() {printf("A");}
};
class B : public A
{
void f() {printf("B");}
};
void g(A& a)
{
a.f();
}
int main()
{
B b;
g(b);
return 0;
}
This may cause serious bugs, and it is suggested to never overload base class methods, and to always use the override keyword when overriding a virtual method to escape those bugs.
When making a static function, you can simply overload it, it would not create a compilation error. However, you probably never should overload it, because it may hide a bug that is very difficult to track (you are certain that B::f() is being called while actually A::f() is being called).
Furthermore, it is not possible to 'force' the derived class to implement a static interface, because there is no such thing as a static interface. Because you have no virtual static functions, you may not pass a reference or pointer to the interface that would implement this function.
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.
What does it mean to have a using inside a class definition?
class myClass {
public:
[...]
using anotherClass::method;
};
That declaration unhides a base class member. This is most often used to allow overloads of a member function. Example:
class Base {
public:
void method() const;
};
class Derived : public Base {
public:
void method(int n) const;
// Without the using, you would get compile errors on d.method();
using Base::method;
};
The case I've seen it:
class A
{
void foo(int);
void foo(float);
}
class B : public A
{
void foo(string);
}
B b;
b.foo(12); // won't work!
Because I have implemented a new foo function in B with a different signature it hides the foo functions from A. In order to override this behavior I would do:
class B : public A
{
void foo(string);
using A::foo;
}
Most often, syntax like this is used like so:
class derived : public base {
public:
[...]
using base::method;
};
The using declaration here unhides a member declaration from the parent class. This is sometimes necessary if another member declaration in derived may hide the member from base.
If anotherClass is a base class that contains a member function like
virtual void f();
and you decide to overload the function in the derived class like
virtual void f(int);
it "hides" f() in the base class. Calling f() through a pointer to the derived class for example, would result in an error, since the compiler does not "see" the version of f() taking no arguments from the base class anymore.
By writing
using Base::f;
you can bring the base classes function back into scope, thus enabling overload resolution as you might have expected it to work in the first place.
Have a base class A, and a derived class B which overrides function template Func:
class A
{
A() {...};
~A() {};
template <class T>
void Func(const String &sInput, T &tResult)
{...}
};
class B : public A
{
B() {...}
~B() {};
template <class T>
void Func(const String &sInput, T &tResult)
{...}
};
(Note that Func is non-virtual, given the lack of support in C++ for templated virtual functions.)
Now have a mainprog API, class M:
class M
{
M(boost::shared_ptr<A> &pInterfaceInput): pInterface(pInterfaceInput)
{}
template <class T>
Evaluate(const String &sInput, T &tResult)
{
pInterface->Func<T>(sInput, tResult);
}
private:
const boost::shared_ptr<A> pInterface;
};
I want the function Evaluate here to support calls to functions on base class A or any of its derived classes (such as B). This class was written with polymorphism in mind before I re-designed class A and B to have templated functions.
Now the problem here is that if I pass a shared pointer of the base type to the derived type then Func of the base class will be called, not the derived class being pointed to.
How do I get around the lack of dynamic polymorphism here?
I've considered making class M a class template on the shared pointer type and having a static_cast in the constructor to ensure this type is of the base class type (A) or of a derived class.
What's the nicest way to do this? I'd prefer not to modify classes A and B to get around this problem but all suggestions are welcome.
Thanks.
Sounds like a double dispatch problem. Perhaps this would be a good place to implement the visitor pattern?
For example, create a class Evaluator, and for each T a subclass ConcreteEvaluator<T>. Give A and B methods that visit the Evaluator. Something like:
class Evaluator
{
virtual void visit_A(A* object);
virtual void visit_B(B* object);
};
template <typename T>
class ConcreteEvaluator : public Evaluator
{
public:
String* input_reference;
T& result_reference;
ConcreteEvaluator(String& input_reference_,T& result_reference_) :
input_reference(input_reference_),
result_reference(result_reference_) {}
virtual void visit_A(A* object) {
object->Func(input_reference,result_reference);
}
virtual void visit_B(B* object) {
object->Func(input_reference,result_reference);
}
}
class A
{
...
virtual void apply_evaluator(Evaluator *eval) {eval->visit_A(this);}
...
}
class B
{
...
virtual void apply_evaluator(Evaluator *eval) {eval->visit_B(this);}
...
}
For each subclass of A, a new method must be added to ConcreteEvaluator, so that this technique works best if A's class hierarchy is stable. And for each subclass of A, it must have an apply_evaluator function defined properly.
On the other hand, this may be total overkill. For about the same amount of work, you could always just pay the price to update M::Evaluate:
class M
{
...
void Evaluate(const String& sInput, T& tResult)
{
// try to downcast to each subclass of A. Be sure to check
// sub-subclasses first
try
{
dynamic_cast<B*>(pInterface.get())->Func(sInput, tResult);
return;
}
catch (std::bad_cast& ) { }
...
// nothing worked. It must really be an A
pInterface->Func(sInput,tResult);
}
...
};
I've show in the question Templatized Virtual function how to use type erasure to get some of the effects of virtual member function. Depending on what you want to do in Func(), you can use the same technique here.