Consider following piece of code:
template.h
template<typename T>
class templ{
public:
virtual const int virtualMethod(const T *const) const = 0;
}
Base.h
#include "template.h"
class Der1;
class Der2;
class Base :
public templ<Base>,
public templ<Der1>,
public templ<Der2>{
public:
virtual ~Base(){}
};
Der1.h
#include "Base.h"
class Der1 : public Base {
public:
virtual const int virtualMethod(const Base *const) const override;
virtual const int virtualMethod(const Der1 *const) const override;
virtual const int virtualMethod(const Der2 *const) const override;
};
Der1.cpp
#include "Der1.h"
const int Der1::virtualMethod(const Base *const sth) const{
return sth->templ<Der1>::virtualMethod(this);//does not work
//how to fix it?
}
const int Der1::virtualMethod(const Der1 *const sth) const{
//do sth
}
const int Der1::virtualMethod(const Der2 *const sth) const{
//do sth
}
Class Der2 also inherits from Base and implements these three functions.
For this code compiler gives me these messages:
'templ' is ambiguous ' Candidates are: templ() templ(const
templ &) templ() templ(const templ &) templ()
templ(const templ &) '
Function 'virtualMethod' could not be resolved
Namespace member function 'virtualMethod' cannot be resolved.
Type 'Der1' cannot be resolved.
undefined reference to
`templ::virtualMethod(Der1 const*) const'
In general, the idea of the code was to implement double type dispatch. Although I think I know what causes problems, I have no idea how to solve it. So maybe you can help me.
I am a little confused what was your intention...
But what about:
const int Der1::virtualMethod(const Base *sth) const {
return dynamic_cast<const templ<Der1> *>(sth)->virtualMethod(this);
}
Related
Consider the following code:
#include <stdio.h>
#include <iostream>
/// Header-file
class Base {
public:
virtual void do_something() const =0;
int GetAttrib () const {return constattribute_;};
static const int constattribute_;
};
typedef Base* Derived_Ptr; //<< adress derived classes by their base-class ptr; so no templates for Base
class DerivedA : public Base {
// static const int constattribute_; //<< change this static attribute for all DerivedA class instances and their derivatives
void do_something() const {};
};
class DerivedB : public Base {
// static const int constattribute_; //<< change this static attribute for all DerivedB class instances and their derivatives
void do_something() const {};
};
/// CC-file
using namespace std;
const int Base::constattribute_(0);
const int DerivedA::constattribute_(1); //<<error: no such variable 'constattribute' in class DerivedA
const int DerivedB::constattribute_(2); //<<error: no such variable 'constattribute' in class DerivedB
int main(void) {
Derived_Ptr derivedA = new DerivedA();
Derived_Ptr derivedB = new DerivedB();
cout << derivedA->GetAttrib() << derivedB->GetAttrib() <<endl;
return 0;
};
The intend being that i have some abstract interface (Base) which defines also a variable, which should be present for all derived classes, and is retrievable. All flavours of subclasses should be forced to/able to redefine their specific value for this variable, at best during class declaration (the values are known at the time the class is declared after all).
I want to achieve code, not altering the main()-program so that the output is '12' and not as of now (uncommenting current lines in the code) '00' (Doing so shadows the fields from base class).
I tried to look into the matter, and there are different paths for solutions, many of which however go contrary to my intuition:
1. Some follow the CRTP pattern, which is however impossible if I want to address my subclasses by their base-ptr in main.
2. Other solutions require to virtualize the 'GetAttrib()' function for every derived instance., which is cumbersome, and action of modifying the attribute is masked within a function definition.
3. A third possibility is to remove the static pattern and have the 'constattribute_' field as a regular member, which however forces me to drag it through all constructors as a parameter.
I am quite sure that there must be some smarter way to do this. Any hints are appreciated.
Using CRTP may get you what you want, assuming you don't have to access GetAttr() through Base* and can leave without constattribute_ in Base itself. Just follow the rule that every programming problem can be solved by entering another level of indirection, which I did below:
class Base {
public:
virtual void do_something() const = 0;
virtual ~Base() // should define it as you are using Base*
{
}
};
typedef Base* Derived_Ptr;
template<class T>
class BaseConstAttr : public Base
{
public:
int GetAttrib () const
{
return(constattribute_);
};
static const int constattribute_;
};
class DerivedA : public BaseConstAttr<DerivedA>
{
public:
void do_something() const
{
};
};
class DerivedB : public BaseConstAttr<DerivedB>
{
public:
void do_something() const
{
};
};
template<> const int BaseConstAttr<DerivedA>::constattribute_(1);
template<> const int BaseConstAttr<DerivedB>::constattribute_(2);
If you need GettAttr from top to bottom of the inheritance tree you can modify the above code a bit, but this will cost you making GetAttr virtual (but still one implementation only):
class Base {
public:
virtual void do_something() const = 0;
virtual int GetAttrib () const = 0;
virtual ~Base() // should define it as you are using Base*
{
}
};
typedef Base* Derived_Ptr;
template<class T>
class BaseConstAttr : public Base
{
public:
int GetAttrib () const
{
return(constattribute_);
};
static const int constattribute_;
};
class DerivedA : public BaseConstAttr<DerivedA>
{
public:
void do_something() const
{
};
};
class DerivedB : public BaseConstAttr<DerivedB>
{
public:
void do_something() const
{
};
};
template<> const int BaseConstAttr<DerivedA>::constattribute_(1);
template<> const int BaseConstAttr<DerivedB>::constattribute_(2);
Please note that I don't know how well (or bad) it will behave with deep inheritance tree (ie. when inheriting from DerivedA and/or DerivedB). In this case I would probably remove BaseConstAttr from inheritance tree right below Base and would try to inject it between most derived class and its predecessor or use multiple inheritance.
What you are requesting requires virtual dispatch somewhere, because you don't know the type of the object you are dealing with until runtime. The purpose of virtual dispatch is to solve exactly the problem you are facing.
The simplest solution is what you have given as number 2: make GetAttrib() virtual, and implement it on each derived class where you introduce a shadowing constattribute_.
static variable in base class is single instance hence it will be reflected same in derived class.
You can make same static member variable in derived class with specific different value you want. Now make getter member function of static variable in Base class as virtual and overload it in derived class which returns is static instance value.
I have update your code to work it, please check ..
#include <iostream>
using namespace std;
class Base {
public:
static const int constattribute_;
virtual void do_something() const =0;
virtual int GetAttrib () const {return constattribute_;};
};
typedef Base* Derived_Ptr; //<< adress derived classes by their base-class ptr; so no templates for Base
class DerivedA : public Base {
static const int constattribute_; //<< change this static attribute for all DerivedA class instances and their derivatives
void do_something() const {};
int GetAttrib () const {return constattribute_;};
};
class DerivedB : public Base {
static const int constattribute_; //<< change this static attribute for all DerivedB class instances and their derivatives
void do_something() const {};
int GetAttrib () const {return constattribute_;};
};
const int Base::constattribute_(0);
const int DerivedA::constattribute_(1); //<<error: no such variable 'constattribute' in class DerivedA
const int DerivedB::constattribute_(2); //<<error: no such variable 'constattribute' in class DerivedB
int main(void) {
Derived_Ptr derivedA = new DerivedA();
Derived_Ptr derivedB = new DerivedB();
cout << derivedA->GetAttrib() << derivedB->GetAttrib() <<endl;
return 0;
};
You should get desired output.
Note : Remember all member variables and func in derived class are private.
I'm an C++ beginner, please help me.
I can't use template class as the constructor' s parameter.
xcode shows 'No matching constructor for initialization of 'Work'' error.
The whole source code below, any one can fix this?
#include <iostream>
class Base {
public:
virtual void hello_world() const {
printf("Base::hello_world()\n");
};
};
class Derived : public Base {
public:
void hello_world() const {
printf("Derived::hello_world()\n");
};
};
template<class T>
class Templ {
public:
Templ(const T &t) : _value(t) {}
const T& getValue() const{
return _value;
}
private:
const T &_value;
};
class Work {
public:
Work(const Templ<Base*> &base) : mBase(base) {}
void working() {
mBase.getValue()->hello_world();
}
private:
const Templ<Base*> &mBase;
};
int main(int argc, const char * argv[]) {
Templ<Base*> base(new Base());
//OK
Work w_base(base);
Templ<Derived*> derived(new Derived());
//error: No matching constructor for initialization of 'Work'
Work w_derived(derived);
return 0;
}
Work w_derived(derived); is never going to work as Work expects a Templ<Base*>. A Templ<Base*> and a Templ<Derived*> are two different, distinct types. Just a like a std::vector<int> is not the same as a std::vector<std::complex>.
What you can do though is create a Templ<Base*> from a pointer to a Dervied and then create a Work with that. Something like
Templ<Base*> derived(new Derived());
Work w_derived(derived);
Live Example
Also as pointed out in the comments since you are using polymorphism you need to have a virtual destructor in the base class. If the destructor is not virtual then only the base class destructor will run and you will your object will not be properly destructed.
In C++, this would look like this
struct Base
{
virtual ~Base() {} // enable descruction of base through pointer to Base
virtual void hello_world() const
{ std::cout<<"Base::hello_world()\n"; }
};
struct Derived : Base
{
void hello_world() const override
{ std::cout<<"Derived::hello_world()\n"; }
};
struct work
{
work(const Base*p)
: ptr(p) {}
void working() const
{ ptr->hello_world(); }
private:
std::unique_ptr<const Base> ptr;
};
int main()
{
Work w_base(new Base);
Work w_derived(new Derived);
w_base.working();
w_derived.working();
}
Note the following
the virtual destructor of Base ensures that a derived class is properly destructed from a pointer to Base, so that std::unique_ptr<> works correctly.
the override keyword ensures that we actually implement a virtual method.
the usage of std::unique_ptr<> avoids the Templ class. Morever, its destructor will automatically and correctly destroy the pointed-to object, avoiding the memory leak of your code.
return 0 is not required for int main(), but automatically generated.
The following code
#include <iostream>
template<typename T>
class Abstract
{
public:
virtual ~Abstract()
{}
virtual void func(const T ¶m) const = 0;
};
class Concrete : public Abstract<int*>
{
public:
virtual void func(const int *¶m) const override // watch out!
{}
};
int main()
{
Concrete c;
}
produces the following compile error at the line marked with the comment:
error C3668: 'Concrete::func' : method with override specifier 'override' did not override any base class methods
If I remove the override, this error will be shown:
error C2259: 'Concrete' : cannot instantiate abstract class
How to derive from Abstract<int*>?
Declare Concrete like this:
class Concrete : public Abstract<int*>
{
public:
virtual void func(int * const ¶m) const override
{}
};
The question is: Which part of the parameter of Abstract<int*>::f() is const?
The answer: Since T is const and T in Abstract<int*> is a pointer (to an int), it is the pointer that is const - not the int.
You want this:
virtual void func(int * const ¶m) const override // watch out!
What I think I need is like a pure virtual function, except the base class does have an implementation which derived classes mustn't default to (and this rule must propagate). The opposite of final?
I have a handful of types derived from a common base. The base is a useful type and some of the derived types are derived from other derived types. I'll be working with references to the base class only, but I need a virtual operator==() which sees through this and calls hand-rolled comparisons appropriate to each situation. A sort of two-dimensional vtable for operator==().
It's important that implementations don't propagate to derived classes, because letting this happen accidentally could result in a comparison between incompatible types falling through to a base class implementation where they are compatible types and this could produce a false positive.
I mean to let specific functionally-equivalent cases compare equal despite them being expressed in different classes. I expect the problem extends to other operations, though, and perhaps my use of operator==() isn't agreeable here.
I don't claim to know C++ -- I'm just a C hack trying to be idiomatic.
Here's what I've worked out so far:
class base;
class foo;
class bar;
class baz;
#define COMPARE public: \
virtual bool equal(base const &p) const; \
virtual bool equal(foo const &p) const; \
virtual bool equal(bar const &p) const; \
virtual bool equal(baz const &p) const; \
virtual bool operator==(base const &p) const { return p.equal(*this); }
class base {
int a_;
public:
base(int a) : a_(a) {}
COMPARE
};
class foo : public base {
int b_;
public:
foo(int a, int b) : base(a), b_(b) {}
COMPARE
};
class bar : public base {
int c_;
public:
bar(int a, int c) : base(a), c_(c) {}
COMPARE
};
class baz : public bar {
int d_;
public:
baz(int a, int c, int d) : bar(a, c), d_(d) {}
COMPARE
};
Now, thanks to COMPARE, all T::equal() must be implemented, and none of them are allowed to fall back on an earlier implementation. Also, every class has its own operator==() which calls the appropriate equal() for its own type (rather than the base class type).
What I want is to enforce these rules in the way that COMPARE does now, but without needing to remember that every derived class has to reference the macro, and ideally (to be C++-idiomatic) without using a macro at all.
What's the proper C++ way to do this?
I'm also still learning, but what you describe sounds a lot like it might need a double dispatch and/or visitor pattern.
For double dispatch, something like:
class base;
class foo;
class bar;
class baz;
class base {
int a_;
public:
base(int a) : a_(a) {}
virtual bool operator==(const base&) const =0;
virtual bool operator==(const foo&) const =0;
virtual bool operator==(const bar&) const =0;
virtual bool operator==(const baz&) const =0;
};
class foo : public base {
int b_;
public:
foo(int a,int b) : base(a),b_(b) {}
bool operator==(const base&) const override;
bool operator==(const foo&) const override;
bool operator==(const bar&) const override;
bool operator==(const baz&) const override;
};
class bar : public base {
int c_;
public:
bar(int a,int c) : base(a),c_(c) {}
bool operator==(const base&) const override;
bool operator==(const foo&) const override;
bool operator==(const bar&) const override;
bool operator==(const baz&) const override;
};
class baz : public bar {
int d_;
public:
baz(int a,int c,int d) : bar(a,c),d_(d) {}
bool operator==(const base&) const override;
bool operator==(const foo&) const override;
bool operator==(const bar&) const override;
bool operator==(const baz&) const override;
};
This already looks a lot like the macro option presented above. :)
From TC++PL 4th edition, section 22.3.1 talking about double dispatch, there is mention of perhaps rather using a precomputed lookup table. Something like
bool equal(const base& b1,const base& b2)
{
auto i = index(type_id(b1),type_id(b2));
return intersect_tbl[i](b1,b2);
}
except the base class does have an implementation which derived classes mustn't default to (and this rule must propagate)
If that is the only problem, then as Ben Voigt mentioned in his comment - it is not a problem, because pure virtual functions can be implemented.
Also, once a derived class overrides, I need the same rule in place,
that the override isn't used by further derived classes (if they must
then they can always call it explicitly in their own implementation)
If that is the case then "idiomatic C++ way" would probably be not to use inheritance to model "derived" - "further derived". Inheritance is typically used to model either substitutability or to model polymorphism, but it is neither here. In other words: model "derived" - "further derived" by composition.
So this appears to be one way of forcing derived classes to provide their own implementations of specific functions:
template<typename T> struct sweep : public T {
template <class... Args> sweep(Args&&... args) : T(args...) { }
virtual bool equal(base const &p) const = 0;
virtual bool equal(foo const &p) const = 0;
virtual bool equal(bar const &p) const = 0;
virtual bool equal(baz const &p) const = 0;
virtual bool operator==(base const &p) const = 0;
};
class base { ... };
class foo : public sweep<base> {
int b_;
public:
foo(int a, int b) : sweep(a), b_(b) {}
...
};
It still requires that the derived class remember to do something specific to constrain itself -- to use the sweep template to derive from the base class -- but it is at least C++ rather than C.
It also has the advantage that the template could refresh the default implementations rather than make them pure virtual; like so:
template<typename T> struct sweep : public T {
...
virtual bool equal(base const &p) const { return false; }
...
};
On the grounds that without further guidance every comparison should fail. This is actually closer to what I need -- but not what I asked for.
How can I override a virtual member function of the following type:
virtual AnimalId func(int index) const
where AnimalId is a typedef unsigned int
I tried several ways but either ending up by an error that I don't give output or that I don't have an overrider at all. I saw on some website that maybe I need to use static const in order to do this, but I don't know how.
In order to override method of signature
virtual AnimalId func(int index) const
declared in base class Base, you have to define function with same signature in derived class:
class Derived : public Base {
public:
virtual AnimalId func(int index) const
{
return 43; // I am using 43 because I think this is
// so much underestimated in favor of 42
}
//...
};
Or you can type override kryword to be more explicit:
class Derived : public Base {
public:
virtual AnimalId func(int index) const override
{
return 43 & 45;
}
//...
};
Did you mean something like: (Note, you have to remove override if you compile for C++03)
typedef unsigned int AnimalId;
class Base
{
public:
virtual ~Base() {}
virtual AnimalId func(int index) const { return 0; }
};
class Derived : public Base
{
public:
AnimalId func(int index) const override { return 42; }
};