mardi 15 avril 2014

modèles - C++: concevoir des conseils - Stack Overflow


I need some advice on the design of my class hierarchy. The 'skeleton' of my current design is


template <class X>
class BASE {
public:
virtual void f() {
x_.f2(m_);
}

void g() {
/* do stuff here*/
x_.g();
}

/* more member functions here*/

protected:
X x_;
int m_;
};

template <class X>
class DERIVED : BASE<X> {
public:
virtual f() override {
x_.f1();
}

protected:
using BASE<X>::x_;
using BASE<X>::m_;
};

and finally I have two more classes like this


struct X1 {
void f1();
void g();
};

struct X2 : X1 {
void f2(int m);
};

I would like to be able to create an instance of DERIVED<X1>. To do that, the compiler will create first an instance of BASE<X1>, in which case it will complain that X1 does not have a member function f2 (even though in practice it would never be called since the calling function f() is virtual).


I understand that this is a bad design since in order to have a templated class, the template arguments must have the same interface. In my case X1 and X2 have a common interface but X2 has more functionality, which creates the above problem. I understand I could create an f2 function in X1 which does nothing, but ideally I would like to avoid that.


I would welcome any suggestions for improving the design. Thanks in advance!




Avoid deriving from a concrete class. Lift interfaces/ABCs to the top, make all concrete classes leaves. It's a general advice for many kinds of design difficulties.


In your particular case, instead of this:


             BASE    // concrete
|
DERIVED

use this:


             BASE   // fully abstract
/ \
BASIC_DERIVED ADVANCED_DERIVED

Now f is pure virtual in BASE and all is well.




First advice is not to use protected atributes. Is is breaking incapsulation.


The second advice is to make virtual void f()=0 pure virtual without implementation. In such there will be no error in the derived class.



I need some advice on the design of my class hierarchy. The 'skeleton' of my current design is


template <class X>
class BASE {
public:
virtual void f() {
x_.f2(m_);
}

void g() {
/* do stuff here*/
x_.g();
}

/* more member functions here*/

protected:
X x_;
int m_;
};

template <class X>
class DERIVED : BASE<X> {
public:
virtual f() override {
x_.f1();
}

protected:
using BASE<X>::x_;
using BASE<X>::m_;
};

and finally I have two more classes like this


struct X1 {
void f1();
void g();
};

struct X2 : X1 {
void f2(int m);
};

I would like to be able to create an instance of DERIVED<X1>. To do that, the compiler will create first an instance of BASE<X1>, in which case it will complain that X1 does not have a member function f2 (even though in practice it would never be called since the calling function f() is virtual).


I understand that this is a bad design since in order to have a templated class, the template arguments must have the same interface. In my case X1 and X2 have a common interface but X2 has more functionality, which creates the above problem. I understand I could create an f2 function in X1 which does nothing, but ideally I would like to avoid that.


I would welcome any suggestions for improving the design. Thanks in advance!



Avoid deriving from a concrete class. Lift interfaces/ABCs to the top, make all concrete classes leaves. It's a general advice for many kinds of design difficulties.


In your particular case, instead of this:


             BASE    // concrete
|
DERIVED

use this:


             BASE   // fully abstract
/ \
BASIC_DERIVED ADVANCED_DERIVED

Now f is pure virtual in BASE and all is well.



First advice is not to use protected atributes. Is is breaking incapsulation.


The second advice is to make virtual void f()=0 pure virtual without implementation. In such there will be no error in the derived class.


Related Posts:

0 commentaires:

Enregistrer un commentaire