简体   繁体   中英

Inheritance issues with template classes

Can anyone figure out a nice way to get the following code to work? (This is, once again, an incredibly simplified way of doing this)

template <class f, class g> class Ptr;

class RealBase { };

template <class a, class b, class c = Ptr<a,b> > class Base : public RealBase { public: Base(){}; };

template <class d, class e> class Derived : public Base <d,e> { public: Derived(){}; void DerivedMethod(){}; }; template <class f, class g> class Ptr { public: Ptr(){}; Ptr(Base<f,g,Ptr<f,g> >* a){in = a;}; Base<f,g,Ptr<f,g> >* operator->() { return in; }; private: Base<f,g,Ptr<f,g> >* in; };

typedef Derived<double,double> DDerived;

int main() { Base<int,int> b = Base<int,int>(); Derived<double,double> d = Derived<double,double>(); DDerived dd = DDerived(); Ptr<double,double> p(&dd); p->DerivedMethod(); return 1; }

At the moment the compiler moans because a Base<> doesn't have a DerivedMethod();

EDIT

I do understand the problem here, my bad for a lack of explanation in the first case (I was in a rush). [This is very cut down code by the way so, yes, for the sake of simplicity I don't have destructors or methods that actually DO anything. Just ignore that, it makes no difference to the problem.]

What I need to happen is that an iterator (that isn't detailed here) that deals only with the derived class (D_Derived) need to access a method that is contained within a derived class and not the base class. Simply plonking this method into the base class isn't really an option because this error is going to occur a LOT if I have to do that. (There are about 10 classes built on the real base class, and they all have derived methods of their own. Like 20 of them. Each.)

Can anyone think of another way to achieve this functionality?

This code doesn't work because template class Ptr returns the object of Class of Base Template not Class of Derived Template.Derived Method is part of derived template so this throws compilation error. Whereas if DerivedMethod was part of Base Template this code will work

That makes sense. Base doesn't have such a method (DerivedMethod). If DerivedMethod were a virtual function (could be pure ) of the base class it'd work.

The compiler is right. In order for you to be able to access a method, this method must be declared in the type that the compiler sees (this is called the static type of a variable). In your case, this type is Base<…> and the compiler has no clue that it's something else.

It is really hard to figure out what you actually want to achieve, using your abstract class and member names. If you really have to treat the pointer within Ptr as a D_Derived , add an accessor member to Ptr and use type casting:

class Ptr {
    ...

    Base<f,g,Ptr<f,g> >* get() {
        return in;
    }
};

...

D_Derived* ptr = dynamic_cast<D_Derived*>(p.get());
if (ptr) {
    ptr->DerivedMethod();
}

EDIT : As Konrad Rudolph pointed out, in order to use dynamic casting, you will have to add a virtual method to your base class.

Actually it is a good practice to define a virtual destructor for every class that you want to use as a base class anyway, to ensure the destructor of your derived class will be called ( More Information ).

class RealBase {
public:
    virtual ~RealBase() {}
};

OK. After trying about 10 different methods ( static_cast , reinterpret_cast etc.) you can just cast it.

int main()
{
    Base&lt;int,int> b = Base&lt;int,int>();
    Derived&lt;double,double> d = Derived&lt;double,double>();
    DDerived dd = DDerived();
    Ptr&lt;double,double> p(&dd);
    DDerived * fauxpointer;
    fauxpointer = (DDerived\*) &(*p);
    fauxpointer->DerivedMethod();
    return 1;
}

Nasty. But it works, and that's all that counts.

Cheers to everyone who repeated the question back at me.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM