I have something like this :
class X
{
method(){...};
void f()=0;
};
class my_X;
class my_Y;
class my_X: public X
{
public:
his_Y* opp;
void f()={...};
};
class his_X: public X
{
public:
my_X* opp;
void f()={...};
};
Now when I want to take profit of polymorphism and use my member opp while calling X::method() g++ says that opp was not declared. Since X is abstract, I thought the compiler would understand that method can only be called from a my_X or his_X in which opp is declared.
One trick I found would be to add a member X* opp to my class X that would subsequently be hidden by my subclasses definitions of opp.
Is this the right solution ? If not is there a solution ? Or does this issue come from a bad class design ?
One of possible solutions
class X
{
method(){... getOpp(); ...};
virtual void f()=0;
virtual X* getOpp() = 0;
};
class my_X;
class my_Y;
class my_X: public X
{
public:
his_Y* opp;
void f()={...};
X* getOpp() override { return opp; }
};
class his_X: public X
{
public:
my_X* opp;
void f()={...};
X* getOpp() override { return opp; }
};
Since X is abstract, I thought the compiler would understand that method can only be called from a my_X or his_X in which opp is declared.
No, it can't understand that. While compiling the class X, it knows nothing about derived classes.
Related
I've got a class Base from which I have two classes, DerivedA and DerivedB as defined below.
template <typename Derived>
class Base{
public:
double interface(){
static_cast<Derived*>(this)->implementation();
}
};
class DerivedA : public Base<DerivedA>{
public:
double implementation(){ return 2.0;}
};
class DerivedB : public Base<DerivedB>{
public:
double implementation(){ return 1.0;}
};
In short, I'm trying to do the following to maintain a collection of objects, some of which are DerivedA and some of which are DerivedB:
std::vector<std::shared_ptr<Derived>>
Which is obviously impossible beacuse I've now made the class Derived a templated class.
Is there any way I can create / maintain a polymorphic collection of objects?
EDIT: Unfortunately, a simple templated structure does not work as the function implementation is templated in my actual program -- so then implementation would have to be a templated pure virtual function, which cannot be. Pardon my lack of explanation.
This answer pertains to the question as it was at the time of this answer.
Don't use CRTP, which is not dynamic polymorphism, to create dynamic polymorphism.
Use a virtual function.
That's what they're for.
class Base
{
private:
virtual
auto implementation() -> double = 0;
public:
auto interface() -> double { return implementation(); }
};
class DerivedA
: public Base
{
private:
auto implementation() -> double override { return 2.0; }
};
class DerivedB
: public Base
{
private:
auto implementation() -> double override { return 1.0; }
};
Alf's suggestion is on target. It is easy to adapt it to your additional requirement. Define an interface with a pure virtual method:
struct BaseInterface {
virtual ~BaseInterface() {}
virtual double interface() = 0;
};
Now, your template base class can derive from the interface:
template <typename Derived>
class Base : BaseInterface {
public:
double interface(){
static_cast<Derived*>(this)->implementation();
}
};
Now, you can create a vector of pointers to the interface:
std::vector<std::shared_ptr<BaseInterface>>
Because Base<DerivedA> is a completely different type compared to Base<DerivedB>, you are right that you can't just do something like std::vector<std::shared_ptr<Base>>, as it would be syntactically invalid and has no meaningful semantics with regards to C++.
One way to achieve what you want and preserve your current CRTP hierarchy is to create a type erasing interface (or is it what it should be called? I'm not sure...). It is basically a wrapper that defines a certain interface in which you could wrap objects that obey that interface.
#include <vector>
#include <memory>
#include <iostream>
class VirtualBase { // Really am not sure what it should be called, sorry
class Interface {
public:
virtual ~Interface() = default;
virtual double get() = 0;
};
template<typename T>
class Impl : public Interface {
T m_impl_obj;
public:
Impl(T impl_obj) : m_impl_obj(std::move(impl_obj)) {}
double get() override {
return m_impl_obj.get();
}
};
std::shared_ptr<Interface> m_obj;
public:
template<typename T>
VirtualBase(T obj) : m_obj(new Impl<T>(std::move(obj))) {}
double get() {
return m_obj->get();
}
};
template <typename Derived>
class Base{
public:
double get(){
return static_cast<Derived*>(this)->implementation();
}
};
class DerivedA : public Base<DerivedA>{
public:
double get(){ return 2.0;}
};
class DerivedB : public Base<DerivedB>{
public:
double get(){ return 1.0;}
};
int main() {
std::vector<VirtualBase> v;
v.emplace_back(DerivedA{});
v.emplace_back(DerivedB{});
for(auto b : v) {
std::cout << b.get() << std::endl;
}
}
Live example
This is quite incomplete, but it should work, at least in my case if I need such a design. An excellent introduction, with explanations and rationales of how and why, is Sean Parent's talk at GoingNative 2013: http://channel9.msdn.com/Events/GoingNative/2013/Inheritance-Is-The-Base-Class-of-Evil . Really, you should see it, including all the other great presentations in GoingNative.
Edit: this is based on an assumption that OP actually needs virtual function templates. This is apparently not the case.
It is not possible to have virtual function templates.
One way to partially simulate them is the Visitor pattern. It is often used to add dynamically dispatched functionality to existing classes. The fact that this added functionality can be templatized is overlooked all too often.
A pseudocode example
class Base
{
virtual void accept (Visitor*) = 0;
}
class Derived1 : public Base
{
void accept(Visitor* v) { v->visit(this); }
}
class Derived2 : public Base
{
void accept(Visitor* v) { v->visit(this); }
}
class Visitor
{
virtual void visit (Derived1*) = 0;
virtual void visit (Derived2*) = 0;
}
template<class X, class Y>
class FooVisitor
{
X x; Y y;
FooVisitor(X x, Y y): x(x), y(y) {}
void visit (Derived1*) { x.func(y); }
void visit (Derived2*) { y.otherfunc(x); }
}
Of course all the downsides of Visitor are here as well.
Suppose that I have a heirarchy of several classes:
class A {
public:
virtual void DoStuff() = 0;
};
class B : public A {
public:
// Does some work
void DoStuff() override;
};
class C : public B {
public:
// Calls B::DoStuff and does other work
void DoStuff() override;
};
It can naively be implemented:
void Derived::DoStuff() {
Base::DoStuff();
...
}
This implementation has a serious problem, I believe: one always has to remember to call base implementation when overrides.
Alternative:
class A {
public:
void DoStuff() {
for (auto& func: callbacks_) {
func(this);
}
}
virtual ~A() = default;
protected:
template <class T>
void AddDoStuff(T&& func) {
callbacks_.emplace_back(std::forward<T>(func));
}
private:
template <class... Args>
using CallbackHolder = std::vector<std::function<void(Args...)>>;
CallbackHolder<A*> callbacks_;
};
Usage:
class Derived : public Base {
public:
Derived() {
AddDoStuff([](A* this_ptr){
static_cast<Derived*>(this_ptr)->DoStuffImpl();
});
}
private:
void DoStuffImpl();
};
However, I believe that it has a good amount of overhead when actually calling DoStuff(), as compared to the first implementation. In the use cases which I saw, possibly long costruction of objects is not a problem (one might also try to implement something like "short vector optimization" if he wants).
Also, I believe that 3 definitions for each DoStuff method is a little too much boilerplate.
I know that it can be very effectively solved by using inheritance pattern simular to CRTP, and one can hide the template-based solution behind interface class (A in the example), but I keep wondering -- shouldn't there be an easier solution?
I'm interested in a good implementation of call DERIVED implementation FROM BASE, if and only if derived class exists and it has an overriding method for long inheritance chains (or something equivalent).
Thanks!
Edit:
I am aware of an idea described in #Jarod42's answer, and I don't find it appropriate because I believe that it is ugly for long inheritance chains -- one has to use a different method name for each level of hierarchy.
You might change your class B to something like:
class A {
public:
virtual ~A() = default;
virtual void DoStuff() = 0;
};
class B : public A {
public:
void DoStuff() final { /*..*/ DoExtraStuff(); }
virtual void DoExtraStuff() {}
};
class C : public B {
public:
void DoExtraStuff() override;
};
I am not sure if I understood correctly but this seems to be addressed pretty good by the "Make public interface non-virtual, virtualize private functions instead" advice.
I think it's orignated in the Open-Closed principle. The technique is as-follows:
#include <iostream>
class B {
public:
void f() {
before_f();
f_();
};
private:
void before_f() {
std::cout << "will always be before f";
}
virtual void f_() = 0;
};
class D : public B{
private:
void f_() override {
std::cout << "derived stuff\n";
}
};
int main() {
D d;
d.f();
return 0;
}
You essentially deprive descendant class of overriding public interface, only customize exposed parts. The base class B strictly enforces that required method is called before actual implementation in derived might want to do. As a bonus you don't have to remember to call base class.
Of course you could make f virtual as well and let D decide.
I've got a class Base from which I have two classes, DerivedA and DerivedB as defined below.
template <typename Derived>
class Base{
public:
double interface(){
static_cast<Derived*>(this)->implementation();
}
};
class DerivedA : public Base<DerivedA>{
public:
double implementation(){ return 2.0;}
};
class DerivedB : public Base<DerivedB>{
public:
double implementation(){ return 1.0;}
};
In short, I'm trying to do the following to maintain a collection of objects, some of which are DerivedA and some of which are DerivedB:
std::vector<std::shared_ptr<Derived>>
Which is obviously impossible beacuse I've now made the class Derived a templated class.
Is there any way I can create / maintain a polymorphic collection of objects?
EDIT: Unfortunately, a simple templated structure does not work as the function implementation is templated in my actual program -- so then implementation would have to be a templated pure virtual function, which cannot be. Pardon my lack of explanation.
This answer pertains to the question as it was at the time of this answer.
Don't use CRTP, which is not dynamic polymorphism, to create dynamic polymorphism.
Use a virtual function.
That's what they're for.
class Base
{
private:
virtual
auto implementation() -> double = 0;
public:
auto interface() -> double { return implementation(); }
};
class DerivedA
: public Base
{
private:
auto implementation() -> double override { return 2.0; }
};
class DerivedB
: public Base
{
private:
auto implementation() -> double override { return 1.0; }
};
Alf's suggestion is on target. It is easy to adapt it to your additional requirement. Define an interface with a pure virtual method:
struct BaseInterface {
virtual ~BaseInterface() {}
virtual double interface() = 0;
};
Now, your template base class can derive from the interface:
template <typename Derived>
class Base : BaseInterface {
public:
double interface(){
static_cast<Derived*>(this)->implementation();
}
};
Now, you can create a vector of pointers to the interface:
std::vector<std::shared_ptr<BaseInterface>>
Because Base<DerivedA> is a completely different type compared to Base<DerivedB>, you are right that you can't just do something like std::vector<std::shared_ptr<Base>>, as it would be syntactically invalid and has no meaningful semantics with regards to C++.
One way to achieve what you want and preserve your current CRTP hierarchy is to create a type erasing interface (or is it what it should be called? I'm not sure...). It is basically a wrapper that defines a certain interface in which you could wrap objects that obey that interface.
#include <vector>
#include <memory>
#include <iostream>
class VirtualBase { // Really am not sure what it should be called, sorry
class Interface {
public:
virtual ~Interface() = default;
virtual double get() = 0;
};
template<typename T>
class Impl : public Interface {
T m_impl_obj;
public:
Impl(T impl_obj) : m_impl_obj(std::move(impl_obj)) {}
double get() override {
return m_impl_obj.get();
}
};
std::shared_ptr<Interface> m_obj;
public:
template<typename T>
VirtualBase(T obj) : m_obj(new Impl<T>(std::move(obj))) {}
double get() {
return m_obj->get();
}
};
template <typename Derived>
class Base{
public:
double get(){
return static_cast<Derived*>(this)->implementation();
}
};
class DerivedA : public Base<DerivedA>{
public:
double get(){ return 2.0;}
};
class DerivedB : public Base<DerivedB>{
public:
double get(){ return 1.0;}
};
int main() {
std::vector<VirtualBase> v;
v.emplace_back(DerivedA{});
v.emplace_back(DerivedB{});
for(auto b : v) {
std::cout << b.get() << std::endl;
}
}
Live example
This is quite incomplete, but it should work, at least in my case if I need such a design. An excellent introduction, with explanations and rationales of how and why, is Sean Parent's talk at GoingNative 2013: http://channel9.msdn.com/Events/GoingNative/2013/Inheritance-Is-The-Base-Class-of-Evil . Really, you should see it, including all the other great presentations in GoingNative.
Edit: this is based on an assumption that OP actually needs virtual function templates. This is apparently not the case.
It is not possible to have virtual function templates.
One way to partially simulate them is the Visitor pattern. It is often used to add dynamically dispatched functionality to existing classes. The fact that this added functionality can be templatized is overlooked all too often.
A pseudocode example
class Base
{
virtual void accept (Visitor*) = 0;
}
class Derived1 : public Base
{
void accept(Visitor* v) { v->visit(this); }
}
class Derived2 : public Base
{
void accept(Visitor* v) { v->visit(this); }
}
class Visitor
{
virtual void visit (Derived1*) = 0;
virtual void visit (Derived2*) = 0;
}
template<class X, class Y>
class FooVisitor
{
X x; Y y;
FooVisitor(X x, Y y): x(x), y(y) {}
void visit (Derived1*) { x.func(y); }
void visit (Derived2*) { y.otherfunc(x); }
}
Of course all the downsides of Visitor are here as well.
I'm writing a wrapper around some autogenerated classes to provide a better interface. I've written a simplified example to demonstrate the problem.
I have a class A which has a pointer to an object of class X, then I have class B (inherits A) which has a pointer to an object of class Y (inherits X).
That's all fine, except that I'm unsure what the best way is to store the pointers to X and Y. I need to be able to manipulate collections of objects of class A and B as if they were all A (with pointers to X being all I'd need there), which works fine with my example below.
My actual question is how best to handle the case of class B which needs to manipulate class Y objects rather than class X. I'm sure there is something quite obvious that I'm missing which I could use here. It feels clumsy to have to repeatedly cast this variable every time I use it and define a method with a different name (e.g. getY) for each class that inherits A that I create. There might be many methods like doStuff all of which would have to be calling getY.
class X {
private:
int i;
public:
X(int i) : i(i) {}
int getI() {
return i;
}
};
class Y : public X {
private:
int j;
public:
Y(int i, int j) : X(i), j(j) {}
int getJ() {
return j;
}
};
class A {
protected:
X* x;
public:
A(X* a) : x(a) {}
X* get() {
return x;
}
};
class B : public A {
public:
B(Y* y) : A(y) {}
private:
//I could create a new function for each class like class B
Y* getY() {
return (Y*)x;
}
public:
void doStuff() {
Y* y = getY();
y->getJ();
std::cout << "J: " << y->getJ() << cout::endl;
}
};
Extract from main:
X* x = new X(5);
Y* y = new Y(5,6);
B b(y);
b.doStuff();
One alternative which occurs to me is that when I construct class B I could initialise a pointer of type Y variable pointing at the same location as the one which be set in X. As long as my pointers were const I think that should be safe from the two references ever pointing to different things.
Any ideas most welcome.
Thanks.
Well, the first thing I would do is break the inheritance relationship between A and B. You say they have a common interface, so start by defining this interface:
class ILibraryWrapper {
public:
virtual X * get() = 0;
};
I assume that A and B share a lot of code (hence the inheritence relationship), so next define a template class to implement the interface and define the common bits:
template <class T> class LibraryWrapper : public ILibraryWrapper {
protected:
T * pointer;
public:
LibraryWrapper( T * value ) : pointer( value ) {}
virtual X * get() override { return static_cast<X *>( this->pointer ); }
};
Finally, define A and B like so:
class A : public LibraryWrapper<X> {
public:
A( X * value ) : LibraryWrapper( value ) {}
};
class B : public LibraryWrapper<Y> {
public:
B( Y * value ) : LibraryWrapper( value ) {}
void doStuff() {
std::cout << "J: " << this->pointer->getJ() << cout::endl;
}
};
Virtually all your code should then deal with ILibraryWrapper pointers or references. If some code absolutely must know the concrete type of the wrapped object, then you can do a dynamic cast:
auto wrapper = dynamic_cast<LibraryWrapper<Y> *>( object );
if( wrapper != nullptr ) {
// ...
}
But generally speaking, it's better to provide all needed functionality in the ILibraryWrapper interface.
As long as Y derives from X, and B derives from A, then this is easy.
Virtual functions can differ by return type as long as those return types are polymorphic. Implement the following in A:
virtual X* Get() const { return x; }
And the following in B:
virtual Y* Get() const { return static_cast< Y* >( A::Get() ); }
My question might not be too correct... What I mean is:
class MyClass
{
public:
MyClass()
{
}
virtual void Event()
{
}
};
class FirstClass : public MyClass
{
string a; // I'm not even sure where to declare this...
public:
FirstClass()
{
}
virtual void Event()
{
a = "Hello"; // This is the variable that I wish to pass to the other class.
}
};
class SecondClass : public MyClass
{
public:
SecondClass()
{
}
virtual void Event()
{
if (a == "Hello")
cout << "This is what I wanted.";
}
};
I hope that this makes at least a little sense...
Edit: _This changed to a.
What you need to do is make SecondClass inherit from FirstClass and declare _This as protected.
class FirstClass : public MyClass
{
protected:
string _This;
public:
and
class SecondClass : public FirstClass
What you got doesn't make sense because classes can only see members and functions from their parents (MyClass in your case). Just because two class inherit from the same parent does not mean they have any relation or know anything about each other.
Also, protected means that all classes that inherit from this class will be able to see its members, but nobody else.
I guess that you need something like this (for a sake of simplicity, I've omitted all the unnecessary code):
class Base{
public:
~Base(){}
protected:
static int m_shared;
};
int Base::m_shared = -1;
class A : public Base{
public:
void Event(){
m_shared = 0;
}
};
class B : public Base{
public:
void Event(){
if (m_shared == 0) {
m_shared = 1;
}
}
};
int _tmain(int argc, _TCHAR* argv[])
{
A a;
B b;
a.Event();
b.Event();
return 0;
}
To explain above, I'll explain the static data members:
Non-static members are unique per class instance and you can't share them between class instances. On the other side, static members are shared by all instances of the class.
p.s. I suggest that you read this book (especially Observer pattern). Also note that above code is not thread-safe.